/* This file is part of AHD Subtitles Maker Professional
   A program can create and edit subtitles

   Copyright © Ala I Hadid 2009 - 2012

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AHD.MKV
{
    public partial class Frm_ImageText : Form
    {
        public Frm_ImageText(VobSubMergedPack pack, int methodIndex)
        {
            InitializeComponent();

            switch (methodIndex)
            {
                case 0://normal method
                    subImage = pack.VobSubPicture.GetBitmap(null, Color.White, Color.Black, Color.WhiteSmoke, Color.WhiteSmoke);
                    AnalyzeImageMethod1();
                    break;
                case 1://none-compressed (large image with small sub-picture)
                    subImage = pack.VobSubPicture.GetBitmap(null, Color.White, Color.Black, Color.WhiteSmoke, Color.WhiteSmoke);
                    //image as same as normal but using method 2 to detect chars. method 2 will cut off the huge unused background
                    AnalyzeImageMethod2();
                    break;
                case 2: //E1 as main, E2 as background
                    subImage = pack.VobSubPicture.GetBitmap(null, Color.White, Color.Black, Color.Black, Color.Blue);
                    AnalyzeImageMethod3();
                    break;
            }
            GetNextImage();
        }
        public string EnteredText
        { get { return TEXT; } }

        string TEXT = "";
        Bitmap subImage;
        int charOffset = 0;
        int currentLineIndex = 0;
        Rectangle selectedRect = Rectangle.Empty;
        List<int> lines = new List<int>();//each value represents line offset pixel
        List<VobCharImage> images = new List<VobCharImage>();
        public bool OK;

        bool IsPixelColorBlack(int x, int y)
        {
            Color c = subImage.GetPixel(x, y);
            return (c.R == 0 && c.G == 0 && c.B == 0);
        }
        bool IsPixelColorWhite(int x, int y)
        {
            Color c = subImage.GetPixel(x, y);
            return (c.R == 0xFF && c.G == 0xFF && c.B == 0xFF);
        }
        bool IsPixelColorBlue(int x, int y)
        {
            Color c = subImage.GetPixel(x, y);
            return (c.R == 0x00 && c.G == 0x00 && c.B == 0xFF);
        }
        //no cut, use white as background
        void AnalyzeImageMethod1()
        {
            lines = new List<int>();
            lines.Add(0);

            bool canAddLine = true;
            //Get how many lines we have
            for (int y = 0; y < subImage.Height; y++)
            {
                bool found = false;
                for (int x = 0; x < subImage.Width; x++)
                {
                    if (IsPixelColorBlack(x, y))
                    {
                        canAddLine = true;
                        found = true;
                        break;
                    }
                }
                if (!found && canAddLine)
                {
                    if (!lines.Contains(y))
                    { lines.Add(y); canAddLine = false; }
                }
            }
            //get chars
            for (int lineIndex = 0; lineIndex < lines.Count; lineIndex++)
            {
                int currentLineOffset = lines[lineIndex];
                int nextLineIndex = 0;
                if (lineIndex == lines.Count - 1)
                {
                    nextLineIndex = subImage.Height;
                }
                else
                {
                    nextLineIndex = lines[lineIndex + 1];
                }
                for (int x = 0; x < subImage.Width; x++)
                {
                    bool isSpace = true;
                    //search fo the top-coordenate of first char
                    for (int y = currentLineOffset; y < nextLineIndex; y++)
                    {
                        bool br = false;
                        if (IsPixelColorBlack(x, y))
                        {
                            isSpace = false;
                            //we found the char , keep scaning horis until we found the stop
                            int width = 0;
                            int height = 0;
                            for (int x1 = x; x1 < subImage.Width; x1++)
                            {
                                bool found = false;
                                for (int y1 = currentLineOffset; y1 < nextLineIndex; y1++)
                                {
                                    if (IsPixelColorBlack(x1, y1))
                                    {
                                        if (!found)
                                            found = true;
                                        if (y1 < y)
                                            y = y1;
                                        if (height < (y1 - y))
                                            height = (y1 - y);
                                    }
                                }
                                if (!found)//we found the end of the char !
                                {
                                    width = x1 - x;
                                    //creat the rectangle
                                    VobCharImage vimg = new VobCharImage();
                                    vimg.LineIndex = lineIndex;
                                    vimg.Rectangle = new Rectangle(x, y, width, height);
                                    //fill the image data
                                    for (int iy = y; iy < height + y; iy++)
                                    {
                                        for (int ix = x; ix < width + x; ix++)
                                        {
                                            Color cl = subImage.GetPixel(ix, iy);
                                            int data = (cl.R << 16) | (cl.G << 8) | cl.B;

                                            vimg.Data.Add(data);
                                        }
                                    }
                                    images.Add(vimg);
                                    x += width;
                                    br = true;
                                    break;
                                }
                            }
                        }
                        else if (!IsPixelColorWhite(x, y))
                        {
                            isSpace = false;
                        }
                        if (br)
                        {
                            break;
                        }
                    }
                    if (isSpace)
                    {
                        if (images.Count > 0)
                        {
                            if (!images[images.Count - 1].IsSpace)
                            {
                                VobCharImage vimg = new VobCharImage();
                                vimg.LineIndex = lineIndex;
                                vimg.IsSpace = true;
                                images.Add(vimg);
                            }
                        }
                        else
                        {
                            VobCharImage vimg = new VobCharImage();
                            vimg.LineIndex = lineIndex;
                            vimg.IsSpace = true;
                            images.Add(vimg);
                        }
                    }
                }
            }
        }
        //cut image, use white as background
        void AnalyzeImageMethod2()
        {
            CutImageUsingWhite();
            lines = new List<int>();
            lines.Add(0);

            bool canAddLine = true;
            //Get how many lines we have
            for (int y = 0; y < subImage.Height; y++)
            {
                bool found = false;
                for (int x = 0; x < subImage.Width; x++)
                {
                    if (IsPixelColorBlack(x, y))
                    {
                        canAddLine = true;
                        found = true;
                        break;
                    }
                }
                if (!found && canAddLine)
                {
                    if (!lines.Contains(y))
                    { lines.Add(y); canAddLine = false; }
                }
            }
            //get chars
            for (int lineIndex = 0; lineIndex < lines.Count; lineIndex++)
            {
                int currentLineOffset = lines[lineIndex];
                int nextLineIndex = 0;
                if (lineIndex == lines.Count - 1)
                {
                    nextLineIndex = subImage.Height;
                }
                else
                {
                    nextLineIndex = lines[lineIndex + 1];
                }
                for (int x = 0; x < subImage.Width; x++)
                {
                    bool isSpace = true;
                    //search fo the top-coordenate of first char
                    for (int y = currentLineOffset; y < nextLineIndex; y++)
                    {
                        bool br = false;
                        if (IsPixelColorBlack(x, y))
                        {
                            isSpace = false;
                            //we found the char , keep scaning horis until we found the stop
                            int width = 0;
                            int height = 0;
                            for (int x1 = x; x1 < subImage.Width; x1++)
                            {
                                bool found = false;
                                for (int y1 = currentLineOffset; y1 < nextLineIndex; y1++)
                                {
                                    if (IsPixelColorBlack(x1, y1))
                                    {
                                        if (!found)
                                            found = true;
                                        if (y1 < y)
                                            y = y1;
                                        if (height < (y1 - y))
                                            height = (y1 - y);
                                    }
                                }
                                if (!found)//we found the end of the char !
                                {
                                    width = x1 - x;
                                    //creat the rectangle
                                    VobCharImage vimg = new VobCharImage();
                                    vimg.LineIndex = lineIndex;
                                    vimg.Rectangle = new Rectangle(x, y, width, height);
                                    //fill the image data
                                    for (int iy = y; iy < height + y; iy++)
                                    {
                                        for (int ix = x; ix < width + x; ix++)
                                        {
                                            Color cl = subImage.GetPixel(ix, iy);
                                            int data = (cl.R << 16) | (cl.G << 8) | cl.B;

                                            vimg.Data.Add(data);
                                        }
                                    }
                                    images.Add(vimg);
                                    x += width;
                                    br = true;
                                    break;
                                }
                            }
                        }
                        else if (!IsPixelColorWhite(x, y))
                        {
                            isSpace = false;
                        }
                        if (br)
                        {
                            break;
                        }
                    }
                    if (isSpace)
                    {
                        if (images.Count > 0)
                        {
                            if (!images[images.Count - 1].IsSpace)
                            {
                                VobCharImage vimg = new VobCharImage();
                                vimg.LineIndex = lineIndex;
                                vimg.IsSpace = true;
                                images.Add(vimg);
                            }
                        }
                        else
                        {
                            VobCharImage vimg = new VobCharImage();
                            vimg.LineIndex = lineIndex;
                            vimg.IsSpace = true;
                            images.Add(vimg);
                        }
                    }
                }
            }
        }
        //cut image, use blue as background
        void AnalyzeImageMethod3()
        {
            CutImageUsingBlue();
            lines = new List<int>();
            lines.Add(0);

            bool canAddLine = true;
            //Get how many lines we have
            for (int y = 0; y < subImage.Height; y++)
            {
                bool found = false;
                for (int x = 0; x < subImage.Width; x++)
                {
                    if (IsPixelColorBlack(x, y))
                    {
                        canAddLine = true;
                        found = true;
                        break;
                    }
                }
                if (!found && canAddLine)
                {
                    if (!lines.Contains(y))
                    { lines.Add(y); canAddLine = false; }
                }
            }
            //get chars
            for (int lineIndex = 0; lineIndex < lines.Count; lineIndex++)
            {
                int currentLineOffset = lines[lineIndex];
                int nextLineIndex = 0;
                if (lineIndex == lines.Count - 1)
                {
                    nextLineIndex = subImage.Height;
                }
                else
                {
                    nextLineIndex = lines[lineIndex + 1];
                }
                for (int x = 0; x < subImage.Width; x++)
                {
                    bool BackgroundColorFound = true;
                    for (int y = currentLineOffset; y < nextLineIndex; y++)
                    {
                        bool br = false;
                        if (IsPixelColorBlack(x, y))
                        {
                            BackgroundColorFound = false;
                            //we found the char , keep scaning horis until we found the stop
                            int width = 0;
                            int height = 0;
                            for (int x1 = x; x1 < subImage.Width; x1++)
                            {
                                bool found = false;
                                for (int y1 = currentLineOffset; y1 < nextLineIndex; y1++)
                                {
                                    if (IsPixelColorBlack(x1, y1))
                                    {
                                        if (!found)
                                            found = true;
                                        if (y1 < y)
                                            y = y1;
                                        if (height < (y1 - y))
                                            height = (y1 - y);
                                    }
                                }
                                if (!found)//we found the end of the char !
                                {
                                    width = x1 - x;
                                    //creat the rectangle
                                    VobCharImage vimg = new VobCharImage();
                                    vimg.LineIndex = lineIndex;
                                    vimg.Rectangle = new Rectangle(x, y, width, height);
                                    //fill the image data
                                    for (int iy = y; iy < height + y; iy++)
                                    {
                                        for (int ix = x; ix < width + x; ix++)
                                        {
                                            Color cl = subImage.GetPixel(ix, iy);
                                            int data = (cl.R << 16) | (cl.G << 8) | cl.B;

                                            vimg.Data.Add(data);
                                        }
                                    }
                                    images.Add(vimg);
                                    x += width;
                                    br = true;
                                    break;
                                }
                            }
                        }
                        else if (!IsPixelColorBlue(x, y))
                        {
                            BackgroundColorFound = false;
                        }
                        if (br)
                        {
                            break;
                        }
                    }
                    if (BackgroundColorFound)
                    {
                        if (images.Count > 0)
                        {
                            if (!images[images.Count - 1].IsSpace)
                            {
                                VobCharImage vimg = new VobCharImage();
                                vimg.LineIndex = lineIndex;
                                vimg.IsSpace = true;
                                images.Add(vimg);
                            }
                        }
                        else
                        {
                            VobCharImage vimg = new VobCharImage();
                            vimg.LineIndex = lineIndex;
                            vimg.IsSpace = true;
                            images.Add(vimg);
                        }
                    }
                }
            }
        }
       
        void CutImageUsingBlue()
        {
            //keep looking until reaching the none-background color
            for (int y = 0; y < subImage.Height; y++)
            {
                bool found = false;
                for (int x = 0; x < subImage.Width; x++)
                {
                    if (!IsPixelColorBlue(x, y))
                    {
                        found = true;
                        break;
                    }
                }
                if (found)//we found it !! start the cut
                {
                    VobCharImage vimg = new VobCharImage();
                    vimg.Rectangle = new Rectangle(0, y, subImage.Width, subImage.Height - y);
                    //fill the image data
                    for (int iy = y; iy < subImage.Height; iy++)
                    {
                        for (int ix = 0; ix < subImage.Width; ix++)
                        {
                            Color cl = subImage.GetPixel(ix, iy);
                            int data = (cl.R << 16) | (cl.G << 8) | cl.B;

                            vimg.Data.Add(data);
                        }
                    }
                    subImage = vimg.ToBitmap();
                    break;
                }
            }
        }
        void CutImageUsingWhite()
        {
            //keep looking until reaching the none-background color
            for (int y = 0; y < subImage.Height; y++)
            {
                bool found = false;
                for (int x = 0; x < subImage.Width; x++)
                {
                    if (!IsPixelColorWhite(x, y))
                    {
                        found = true;
                        break;
                    }
                }
                if (found)//we found it !! start the cut
                {
                    VobCharImage vimg = new VobCharImage();
                    vimg.Rectangle = new Rectangle(0, y, subImage.Width, subImage.Height - y);
                    //fill the image data
                    for (int iy = y; iy < subImage.Height; iy++)
                    {
                        for (int ix = 0; ix < subImage.Width; ix++)
                        {
                            Color cl = subImage.GetPixel(ix, iy);
                            int data = (cl.R << 16) | (cl.G << 8) | cl.B;

                            vimg.Data.Add(data);
                        }
                    }
                    subImage = vimg.ToBitmap();
                    break;
                }
            }
        }

        void GetNextImage()
        {
            //first, check if we have this image data
            if (images[charOffset].IsSpace)
            {
                TEXT += " ";
                //jump to next
                JumpToNextImage();
            }
            else if (VobcharImagesComparer.IsImageExist(images[charOffset]))
            {
                //we have it, get the text
                VobCharImage img = VobcharImagesComparer.GetSameImage(images[charOffset]);
                if (images[charOffset].LineIndex != currentLineIndex)
                {
                    TEXT += "\n" + img.TheChar;
                    currentLineIndex = images[charOffset].LineIndex;
                }
                else
                {
                    TEXT += img.TheChar;
                }
                //jump to next
                JumpToNextImage();
            }
            else//give the user option to enter the char
            {
                textBox1.Text = "";
                textBox1.Select();
                pictureBox1.Invalidate();
            }
        }
        void JumpToNextImage()
        {
            if (charOffset < images.Count - 1)
            { charOffset++; GetNextImage(); }
            else
            {
                OK = true;
                this.DialogResult = System.Windows.Forms.DialogResult.OK;
                Close();
            }
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(subImage, new Rectangle(0, 0, subImage.Width, subImage.Height));

            if (charOffset < images.Count)
            {
                e.Graphics.DrawRectangle(new Pen(Brushes.DarkRed, 2), images[charOffset].Rectangle);

                pictureBox_current.Image = images[charOffset].ToBitmap();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (textBox1.Text.Length > 0)//add picture only if a text entered
            {
                images[charOffset].TheChar = textBox1.Text;
                if (images[charOffset].LineIndex != currentLineIndex)
                {
                    TEXT += "\n" + images[charOffset].TheChar;
                    currentLineIndex = images[charOffset].LineIndex;
                }
                else
                {
                    TEXT += images[charOffset].TheChar;
                }
                VobcharImagesComparer.CompareImages.Add(images[charOffset]);
            }
            JumpToNextImage();
        }

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            Close();
        }

        private void pictureBox_current_Paint(object sender, PaintEventArgs e)
        {

        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            /*if (e.X < subImage.Width && e.Y < subImage.Height)
            {
                Color c = subImage.GetPixel(e.X,e.Y);
                string red = c.R.ToString();
                string blue = c.B.ToString();
                string green = c.G.ToString();
                label1.Text = "red=" + red + ", green=" + green + ", blue=" + blue;
            }*/
        }
    }
}
