using iTextSharp.text.pdf.parser;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;

namespace ZionGraphics.Pdf.Text
{
    public class OnSetTextExtractionStrategy : LocationTextExtractionStrategy
    {
        public int PageHeight;
        public List<RectAndText> data = new List<RectAndText>();

        public OnSetTextExtractionStrategy(int pageHeight)
        {
            var culture = new System.Globalization.CultureInfo("pt-BR");
            System.Threading.Thread.CurrentThread.CurrentCulture = culture;
            System.Threading.Thread.CurrentThread.CurrentUICulture = culture;

            this.PageHeight = pageHeight;
        }
        public string FullText { get; set; }
        public ZionVault.Binder.OCR.Page Content
        {
            get
            {
                if (data == null || data.Count < 1)
                {
                    return null;
                }

                try
                {

                    var Y = (from content in data
                             select content.Rect.Top).Distinct();

                    List<ZionVault.Binder.OCR.Line> Lines = new List<ZionVault.Binder.OCR.Line>();
                    int l = 0;
                    foreach (int y in Y)
                    {
                        List<ZionVault.Binder.OCR.Word> Words = new List<ZionVault.Binder.OCR.Word>();

                        var LineContent = (from item in data where item.Rect.Top == y select item).ToList();

                        int w = 0;
                        foreach (var item in LineContent)
                        {
                            var last = Words.Count() > 0 ? Words.Last() : null;

                            if (last == null || last.Location.Top != item.Rect.Top)
                            {
                                Words.Add(new ZionVault.Binder.OCR.Word(w, 100, new ZionVault.Basic.Location(
                                    item.Rect.Top, item.Rect.Right, item.Rect.Bottom, item.Rect.Left), item.Text.Trim()));
                                w++;
                            }
                            else
                            {
                                if (item.Rect.Left - last.Location.Right < 
                                   (last.Text.Length > 0 ? (last.Location.Rect.Width / last.Text.Length) : 1))
                                {
                                    last.Text += item.Text;
                                    last.Location.Right += item.Rect.Left - last.Location.Right + item.Rect.Width;
                                }
                                else
                                {
                                    Words.Add(new ZionVault.Binder.OCR.Word(w, 100, new ZionVault.Basic.Location(
                                        item.Rect.Top, item.Rect.Right, item.Rect.Bottom, item.Rect.Left), item.Text.Trim()));
                                    w++;
                                }

                            }
                        }

                        if (Words.Count > 0)
                        {
                            Lines.Add(
                                new ZionVault.Binder.OCR.Line(l, new ZionVault.Basic.Location(
                                    Words.First().Location.Top, Words.Last().Location.Right,
                                    Words.First().Location.Bottom,
                                    Words.First().Location.Left), Words));
                        }
                        l++;

                    }

                    List<ZionVault.Binder.OCR.Paragraph> p = new List<ZionVault.Binder.OCR.Paragraph>();
                    p.Add(new ZionVault.Binder.OCR.Paragraph(
                        0, new ZionVault.Basic.Location(
                                Lines.First().Location.Top, Lines.Last().Location.Right,
                                Lines.First().Location.Bottom,
                                Lines.First().Location.Left),
                        Lines
                    ));


                    List<ZionVault.Binder.OCR.Area> a = new List<ZionVault.Binder.OCR.Area>();
                    a.Add(new ZionVault.Binder.OCR.Area(
                        0, new ZionVault.Basic.Location(
                                p.First().Location.Top,
                                p.Last().Location.Right,
                                p.First().Location.Bottom,
                                p.First().Location.Left),
                        p
                    ));

                    return new ZionVault.Binder.OCR.Page(0, "", a, null);
                }
                catch (Exception e)
                {
                    throw new Exception(e.Message);
                }
            }
        }

        public object Words { get; internal set; }

        public override void RenderText(TextRenderInfo renderInfo)
        {
            base.RenderText(renderInfo);

            var chars = renderInfo.GetCharacterRenderInfos();

            var bottomLeft = renderInfo.GetDescentLine().GetStartPoint();
            var topRight = renderInfo.GetAscentLine().GetEndPoint();

            var rect = new iTextSharp.text.Rectangle(
                    bottomLeft[Vector.I1],
                    bottomLeft[Vector.I2],
                    topRight[Vector.I1],
                    topRight[Vector.I2]
                );

            string fontName = @"Verdana";

            double fontSize = rect.Height == 0 ? 1 : rect.Height * 0.65;

            string text = renderInfo.GetText();

            var x = Math.Floor(rect.Width);
            var avgCharLength = (int)Math.Floor(Math.Floor(rect.Width) / text.Length);
            bool bold = fontName.ToLower().Contains("bold");
            var a = renderInfo.GetText();
            var adfsa = renderInfo.GetText().Split(' ');

            foreach (string word in renderInfo.GetText().Split(' '))
            {
                if (word.Length > 0)
                {
                    int positionX = (int)rect.Left;

                    if (this.data.Where(rec => rec.Rect.Top == this.PageHeight - (int)rect.Top).Count() > 0)
                    {
                        int lastRight = this.data.Where(rec => rec.Rect.Top == this.PageHeight - (int)rect.Top).Last().Rect.Right + avgCharLength;
                        if (lastRight > positionX)
                            positionX = lastRight;
                    }

                    if (fontSize < 0)
                        fontSize *= -1;
                    if (fontSize < 1)
                        fontSize = 10;

                    this.data.Add(new RectAndText(
                        new Rectangle(positionX, this.PageHeight - (int)rect.Top, word.Length * avgCharLength, (int)rect.Height),
                        word,
                        new Font(fontName, (int)fontSize, bold ? FontStyle.Bold : FontStyle.Regular),
                        renderInfo.GetSingleSpaceWidth()
                    ));
                }
            }
        }
    }
}