using Emgu.CV;
using Emgu.CV.Structure;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Reflection;

namespace BrightErrorsLed
{
    public partial class BrightErrosLed : Form
    {
        private Bitmap MyNewBitmap { get; set; }
        private Controller Controller = new Controller();
        private Rectangle resolution = Screen.PrimaryScreen.Bounds;
        private bool vertical = false, horizontal = false;
        private Nullable<MyLine>[] HorizontalLines = new Nullable<MyLine>[Screen.PrimaryScreen.Bounds.Height * Screen.PrimaryScreen.Bounds.Width];
        private Nullable<MyLine>[] VerticalLines = new Nullable<MyLine>[Screen.PrimaryScreen.Bounds.Width * Screen.PrimaryScreen.Bounds.Height];
        private int indexVertical = 0;
        private int indexHorizontal = 0;
        private int MyWidth = 0;
        private int MyHeight = 0;
        private Point[] LinePoints;
        private Pen MyPen = new Pen(Color.FromArgb(90, 20, 20, 10), 2);
        private int endPoint = 0, countEnd = 0, n = 0, HorizontalLinesCount = 0, VercitalLinesCount = 0;
        private string image;
        private Image<Hls, Byte> HlsBitmap = new Image<Hls, byte>(new Size());
        public static bool changedFlag { get; set; }
        public static bool Cancel = false;

        public BrightErrosLed()
        {
            changedFlag = false;
            InitializeComponent();
        }

        private void OpenBtn_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif|Png Image|*.png";
                ofd.Title = "Open an Image File";
                ofd.ShowDialog();

                image = ofd.FileName;
                if (image != "")
                {
                    Bitmap bitm = new Bitmap(image);
                    MyNewBitmap = Controller._resize(bitm, resolution.Width, resolution.Height);
                    MainScreen.Image = MyNewBitmap;
                    BrightnessIntensity.Enabled = true;
                    VideoBtn.Enabled = true;
                    SaveImgBtn.Enabled = true;
                    SaveChBtn.Enabled = true;
                }
            }
            catch
            {
                MainScreen.Image = null;
                MessageBox.Show("Application can't read this file.");
            }
        }

        private void HorizontalLinesBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            indexHorizontal = HorizontalLinesBox.SelectedIndex;
            horizontal = true;
            vertical = false;
        }

        private async void VideoBtn_Click(object sender, EventArgs e)
        {
            try
            {
                object fourcc = null;
                var item = KodekBox.SelectedItem;
                if (item != null)
                    fourcc = ((string)item).ToArray();

                VideoBtn.Enabled = false;
                SaveChBtn.Enabled = false;
                OpenBtn.Enabled = false;
                var Bitmap1 = new Bitmap(image);
                Bitmap1 = Controller._resize(Bitmap1, resolution.Width, resolution.Height);
                var Bitmap2 = new Bitmap(MyNewBitmap);

                GC.Collect();
                panel1.Visible = true;
                var progress = new Progress<int>(
                    v =>
                    {
                        progressBar1.Value = v;
                        label5.Text = "Remastering the video. Please wait... Progress: " + progressBar1.Value + " %";
                        if (progressBar1.Value > 0)
                            progressBar1.Visible = true;
                    });

                await Controller.UpChangesToVideoFile(Bitmap1, Bitmap2, label5, progress, (char[])fourcc, changedFlag);
                panel1.Visible = false;
                progressBar1.Visible = false;
                label5.Visible = false;

                VideoBtn.Enabled = true;
                SaveChBtn.Enabled = true;
                OpenBtn.Enabled = true;

            }
            catch
            {
                MessageBox.Show("Sorry, but last image that has been choosen(" + image.ToString() + ") can't be read, please choose other image.");
                VideoBtn.Enabled = true;
                SaveChBtn.Enabled = true;
                OpenBtn.Enabled = true;
            }
        }

        private void SaveChBtn_Click(object sender, EventArgs e)
        {
            if (MainScreen.Image == null)
            {
                MessageBox.Show("There was nothing to be saved");
                return;
            }
            MyNewBitmap = new Bitmap(MainScreen.Image);
            MessageBox.Show("Changes have been saved");
            changedFlag = true;
        }

        private void VericalLinesBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            indexVertical = VericalLinesBox.SelectedIndex;
            vertical = true;
            horizontal = false;
        }

        private void CancelBtn_Click(object sender, EventArgs e)
        {
            var dialog = MessageBox.Show("Sure want cancel this process?", "Cancel", MessageBoxButtons.YesNo);
            if (dialog == DialogResult.Yes)
                Cancel = true;
        }

        private void SaveImgBtn_Click(object sender, EventArgs e)
        {

            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif";
            saveFileDialog1.Title = "Save an Image File";
            saveFileDialog1.ShowDialog();


            if (saveFileDialog1.FileName != "")
            {

                FileStream fs =
                   (FileStream)saveFileDialog1.OpenFile();

                switch (saveFileDialog1.FilterIndex)
                {
                    case 1:
                        this.MyNewBitmap.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Jpeg);
                        break;

                    case 2:
                        this.MyNewBitmap.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Bmp);
                        break;

                    case 3:
                        this.MyNewBitmap.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Gif);
                        break;
                }

                fs.Close();
            }
        }

        private void GreenBtn_Click(object sender, EventArgs e)
        {
            MyPen.Color = Color.Green;
            this.Invalidate(true);
        }

        private void RedBtn_Click(object sender, EventArgs e)
        {
            MyPen.Color = Color.Red;
            this.Invalidate(true);
        }

        private void BlueBtn_Click(object sender, EventArgs e)
        {
            MyPen.Color = Color.Blue;
            this.Invalidate(true);
        }

        private void ShowLinesBtn_Click(object sender, EventArgs e)
        {
            vertical = false;
            horizontal = false;
            this.Invalidate(true);
        }

        private void DefaultColorBtn_Click(object sender, EventArgs e)
        {
            MyPen.Color = Color.FromArgb(90, 20, 20, 10);
            this.Invalidate(true);
        }

        private async void BrightErrosLed_KeyDown(object sender, KeyEventArgs e)
        {
            if (!BrightnessIntensity.Enabled)
                return;
            if (e.KeyCode == Keys.Left)
                BrighValue.Text = BrightnessIntensity.Value--.ToString();
            else if (e.KeyCode == Keys.Right)
                BrighValue.Text = BrightnessIntensity.Value++.ToString();
            if (vertical)
            {
                MainScreen.Image = await Controller.SetLineBrightness(BrightnessIntensity.Value, MyNewBitmap, VerticalLines[indexVertical].Value.getPoints());
            }

            else if (horizontal)
            {
                MainScreen.Image = await Controller.SetLineBrightness(BrightnessIntensity.Value, MyNewBitmap, HorizontalLines[indexHorizontal].Value.getPoints());
            }
            this.Invalidate(true);
        }

        private void FullScreenBtn_Click(object sender, EventArgs e)
        {
            BrightErrosLed.ActiveForm.WindowState = FormWindowState.Maximized;
            BrightErrosLed.ActiveForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            MainScreen.Dock = DockStyle.Fill;
            OpenBtn.Visible = false;
            BrightnessIntensity.Visible = false;
            FullScreenBtn.Visible = false;
            BrighValue.Visible = false;
            Brigh.Visible = false;
            WidthText.Visible = false;
            HeightText.Visible = false;
            label1.Visible = false;
            label2.Visible = false;
            label3.Visible = false;
            label4.Visible = false;
            OkBtn.Visible = false;
            HorizontalLinesBox.Visible = false;
            VericalLinesBox.Visible = false;
            VideoBtn.Visible = false;
            label6.Visible = false;
            SaveChBtn.Visible = false;
            SaveImgBtn.Visible = false;
            ShowLinesBtn.Visible = false;
            GreenBtn.Visible = false;
            RedBtn.Visible = false;
            BlueBtn.Visible = false;
            DefaultColorBtn.Visible = false;
            KodekBox.Visible = false;
        }

        private void MainScreen_DoubleClick(object sender, EventArgs e)
        {
            if (MainScreen.Dock == DockStyle.Fill)
            {
                MainScreen.Dock = DockStyle.None;
                BrightErrosLed.ActiveForm.WindowState = FormWindowState.Normal;
                BrightErrosLed.ActiveForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
                OpenBtn.Visible = true;
                BrightnessIntensity.Visible = true;
                FullScreenBtn.Visible = true;
                Brigh.Visible = true;
                BrighValue.Visible = true;
                WidthText.Visible = true;
                HeightText.Visible = true;
                label1.Visible = true;
                label2.Visible = true;
                label3.Visible = true;
                label4.Visible = true;
                OkBtn.Visible = true;
                HorizontalLinesBox.Visible = true;
                VericalLinesBox.Visible = true;
                VideoBtn.Visible = true;
                label6.Visible = true;
                SaveChBtn.Visible = true;
                SaveImgBtn.Visible = true;
                ShowLinesBtn.Visible = true;
                GreenBtn.Visible = true;
                RedBtn.Visible = true;
                BlueBtn.Visible = true;
                DefaultColorBtn.Visible = true;
                KodekBox.Visible = true;
            }
            else
            {
                BrightErrosLed.ActiveForm.WindowState = FormWindowState.Maximized;
                BrightErrosLed.ActiveForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                MainScreen.Dock = DockStyle.Fill;
                OpenBtn.Visible = false;
                BrightnessIntensity.Visible = false;
                FullScreenBtn.Visible = false;
                BrighValue.Visible = false;
                Brigh.Visible = false;
                WidthText.Visible = false;
                HeightText.Visible = false;
                label1.Visible = false;
                label2.Visible = false;
                label3.Visible = false;
                label4.Visible = false;
                OkBtn.Visible = false;
                HorizontalLinesBox.Visible = false;
                VericalLinesBox.Visible = false;
                VideoBtn.Visible = false;
                label6.Visible = false;
                SaveChBtn.Visible = false;
                SaveImgBtn.Visible = false;
                ShowLinesBtn.Visible = false;
                GreenBtn.Visible = false;
                RedBtn.Visible = false;
                BlueBtn.Visible = false;
                DefaultColorBtn.Visible = false;
                KodekBox.Visible = false;
            }
        }

        private void OkBtn_Click(object sender, EventArgs e)
        {
            int n;
            bool message = false;
            if ((int.TryParse(WidthText.Text.ToString(), out n)) && (resolution.Width % n) == 0)
                MyWidth = Convert.ToInt32(n);
            else
            {
                MessageBox.Show("Program can't split your screen using clusters with this size.\nResolution of your screen is " + resolution.Size.ToString());
                message = true;
            }
            if ((int.TryParse(HeightText.Text.ToString(), out n)) && (resolution.Height % n) == 0)
                MyHeight = Convert.ToInt32(n);
            else if (!message)
            {
                MessageBox.Show("Program can't split your screen using clusters with this size.\nResolution of your screen is " + resolution.Size.ToString());
                message = true;
            }
            if (!message)
                ShowLinesBtn.Enabled = true;
            this.Invalidate(true);
        }

        private void MainScreen_Paint(object sender, PaintEventArgs e)
        {
            if (vertical) return;
            else if (horizontal) return;

            if (MainScreen.Image != null && MyHeight > 0)
            {
                int CurrentVerticalLinesCount = VercitalLinesCount;
                int CurrentHorizontalLinesCount = HorizontalLinesCount;
                n = 0;
                for (int i = 1; i < (resolution.Height / MyHeight); i++)
                {
                    e.Graphics.DrawLine(MyPen, 0, i * MyHeight, resolution.Width, i * MyHeight);
                    LinePoints = new Point[(2 * MyWidth)];
                    DalsiaCiara: for (int j = 0; j < MyWidth; j++)
                    {
                        LinePoints[j] = new Point(j + endPoint, i * MyHeight);
                        LinePoints[j + (MyWidth)] = new Point(j + endPoint, i * MyHeight - 1);
                        countEnd = j;
                    }
                    endPoint += countEnd;
                    HorizontalLines[n] = new MyLine(LinePoints);
                    LinePoints = null;
                    LinePoints = new Point[2 * MyWidth];
                    if (endPoint != (resolution.Width - 1)) { n++; endPoint++; goto DalsiaCiara; }
                    else {
                        endPoint = 0; n++; HorizontalLinesCount = 0;
                        int p = 0;
                        for (int t = 0; t < HorizontalLines.Length; t++)
                        {
                            if (HorizontalLines[t] != null) p++;
                            else break;
                        }
                        for (int y = 0; y < p; y++)
                        {
                            HorizontalLinesCount++;
                        }
                        if (CurrentHorizontalLinesCount != HorizontalLinesCount)
                        {
                            HorizontalLinesBox.Items.Clear();
                            if (HorizontalLinesCount == 0)
                            {
                                HorizontalLinesBox.Items.Clear(); HorizontalLinesBox.Items.Add("No Line");
                            }
                            else
                            {
                                for (int y = 1; y <= HorizontalLinesCount; y++)
                                {
                                    HorizontalLinesBox.Items.Add("Horizontal Line number:" + y);
                                }
                            }
                            CurrentHorizontalLinesCount = HorizontalLinesCount;
                        }

                    }
                }
                n = 0;
                for (int i = 1; i < (resolution.Width / MyWidth); i++)
                {
                    e.Graphics.DrawLine(MyPen, i * (int)MyWidth, 0, i * (int)MyWidth, resolution.Height);
                    LinePoints = new Point[(2 * ((MyHeight)))];
                    DalsiaCiara: for (int j = 0; j < (MyHeight); j++)
                    {
                        LinePoints[j] = new Point(i * MyWidth, j + endPoint);
                        LinePoints[j + ((MyHeight))] = new Point(i * MyWidth - 1, j + endPoint);
                        countEnd = j;
                    }
                    endPoint += countEnd;
                    VerticalLines[n] = new MyLine(LinePoints);
                    LinePoints = null;
                    LinePoints = new Point[2 * MyHeight];
                    if (endPoint != (resolution.Height - 1)) { n++; endPoint++; goto DalsiaCiara; }
                    else
                    {
                        endPoint = 0; n++; VercitalLinesCount = 0;
                        int p = 0;
                        for (int t = 0; t < VerticalLines.Length; t++)
                        {
                            if (VerticalLines[t] != null) p++;
                            else break;
                        }
                        for (int y = 0; y < p; y++)
                        {
                            VercitalLinesCount++;
                        }
                        if (CurrentVerticalLinesCount != VercitalLinesCount)
                        {
                            VericalLinesBox.Items.Clear();
                            if (VercitalLinesCount == 0)
                            {
                                VericalLinesBox.Items.Clear(); VericalLinesBox.Items.Add("No Line");
                            }
                            else
                            {
                                for (int y = 1; y <= VercitalLinesCount; y++)
                                {
                                    VericalLinesBox.Items.Add("Vertical Line number:" + y);
                                }
                            }
                            CurrentVerticalLinesCount = VercitalLinesCount;
                        }

                    }
                }
            }
        }

        private async void BrightnessIntensity_Scroll(object sender, EventArgs e)
        {
            BrighValue.Text = BrightnessIntensity.Value.ToString();
            if (vertical)
            {
                MainScreen.Image = await Controller.SetLineBrightness(BrightnessIntensity.Value, MyNewBitmap, VerticalLines[indexVertical].Value.getPoints());
            }

            else if (horizontal)
            {
                MainScreen.Image = await Controller.SetLineBrightness(BrightnessIntensity.Value, MyNewBitmap, HorizontalLines[indexHorizontal].Value.getPoints());
            }
            this.Invalidate(true);

        }
    }
}
