using DataClients;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;
using PdfSharp.Drawing;
using PdfSharp.Fonts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Mailing
{
	public static class CreatePDF
	{
    public static void PDFSZO(List<List<SZOWork>> data, DateTime date)
    {
      //Create Documents
      Document doc = new Document();

      //Create Fonts
      EZFontResolver fontRes = EZFontResolver.Get;
      GlobalFontSettings.FontResolver = fontRes;
      fontRes.AddFont("TNR", XFontStyle.Regular, @"./times.ttf");
      fontRes.AddFont("TNR", XFontStyle.Bold, @"./timesbd.ttf");
      fontRes.AddFont("TNR", XFontStyle.BoldItalic, @"./timesbi.ttf");
      fontRes.AddFont("TNR", XFontStyle.Italic, @"./timesi.ttf");

      //Create page
      Section page = doc.AddSection();
      page.PageSetup.PageFormat = PageFormat.A4;
      page.PageSetup.Orientation = Orientation.Portrait;
      page.PageSetup.BottomMargin = new Unit(20, UnitType.Millimeter);
      page.PageSetup.TopMargin = new Unit(20, UnitType.Millimeter);
      page.PageSetup.LeftMargin = new Unit(30, UnitType.Millimeter);
      page.PageSetup.RightMargin = new Unit(15, UnitType.Millimeter);

      //Create Format
      var title = page.AddParagraph();
      title.Format.Alignment = ParagraphAlignment.Center;
      title.Format.Font.Size = 14;
      title.Format.Font.Name = "TNR";
      title.Format.SpaceAfter = new Unit(10, UnitType.Millimeter);

      //Header
      title.AddText("Контроль работы водокольцевых насосов SZO\n");
      title.AddText("за " + date.ToString("dd.MM.yyyy") + "\n");

      var totalTime = new TimeSpan();
      for (var i = 0; i < data.Count; i++)
      {
        if (i==9 || i == 18 || i == 21 || i == 24 || i == 46 || i == 30 || i == 41)
          continue;
        if (data[i].Count == 0)
          continue;

        //Create Format
        title = doc.LastSection.AddParagraph();
        title.Format.Alignment = ParagraphAlignment.Left;
        title.Format.Font.Size = 12;
        title.Format.Font.Name = "TNR";
        title.Format.SpaceAfter = new Unit(2, UnitType.Millimeter);

        //Add Title for Table
        title.AddText("Работа SZO печи №" + (i + 1).ToString("D2") + "\n");

        //Create Table
        var table = doc.LastSection.AddTable();
        table.Format.Alignment = ParagraphAlignment.Center;
        table.Format.Font.Size = 12;
        table.Format.Font.Name = "TNR";

        table.Style = "Table";
        table.Borders.Color = new Color(0, 0, 0);
        table.Borders.Width = 0.25;
        table.Borders.Left.Width = 0.5;
        table.Borders.Right.Width = 0.5;
        table.Rows.LeftIndent = 0;

        double[] colSize = { 5 , 4, 5, 3 };
        foreach (var e in colSize)
          table.AddColumn(new Unit(e, UnitType.Centimeter));

        //Add Header for Table
        var row = table.AddRow();
        row.HeadingFormat = true;
        row.VerticalAlignment = VerticalAlignment.Center;
        row.Format.Font.Bold = true;

        row.Cells[0].AddParagraph("Начало тех. цикла");
        row.Cells[1].AddParagraph("Название тех. цикла");
        row.Cells[1].MergeDown = 1;
        row.Cells[2].AddParagraph("Начало работы SZO");
        row.Cells[3].AddParagraph("Время работы SZO");
        row.Cells[3].MergeDown = 1;

        row = table.AddRow();
        row.HeadingFormat = true;
        row.VerticalAlignment = VerticalAlignment.Center;
        row.Format.Font.Bold = true;

        row.Cells[0].AddParagraph("Конец тех. цикла");
        row.Cells[2].AddParagraph("Конец работы SZO");

        //Add Row in Table
        var totalTimeVDP = new TimeSpan();

        for (var j = 0; j < data[i].Count;)
				{
          var currCycle = data[i][j].tc;
          var currSZO = new List<SZOWork>();

          while (j < data[i].Count)
					{
            if (data[i][j].tc != currCycle) break;
            totalTimeVDP = totalTimeVDP.Add(data[i][j].workTime.Subtract(new TimeSpan(00, 15, 00)));
            currSZO.Add(data[i][j]);
            j++;
					}

          for (var k = 0; k < currSZO.Count; k++)
					{
            row = table.AddRow();
            row.HeadingFormat = true;
            row.VerticalAlignment = VerticalAlignment.Center;

            if (k == 0)
						{
              row.Cells[0].AddParagraph(currCycle.start.ToString(@"yyyy.MM.dd HH:mm:ss"));
              if (currSZO.Count > 1)
                row.Cells[0].MergeDown = currSZO.Count - 1;

              row.Cells[1].AddParagraph(Names.techCycle[(int)currCycle.index]);
              row.Cells[1].MergeDown = currSZO.Count * 2 - 1;
            }

            row.Cells[2].AddParagraph(currSZO[k].tStart.ToString(@"HH\:mm\:ss"));
            row.Cells[3].AddParagraph(currSZO[k].workTime.Subtract(new TimeSpan(00, 15, 00)).ToString(@"hh\:mm\:ss"));
            row.Cells[3].MergeDown = 1;

            if (currSZO.Count / 2 == k && currSZO.Count % 2 == 0)
            {
              row.Cells[0].AddParagraph(currCycle.end.ToString(@"yyyy.MM.dd HH:mm:ss"));
              if (currSZO.Count > 1)
                row.Cells[0].MergeDown = currSZO.Count - 1;
            }

            row = table.AddRow();
            row.HeadingFormat = true;
            row.VerticalAlignment = VerticalAlignment.Center;

            if (currSZO.Count / 2 == k && currSZO.Count % 2 == 1)
            {
              row.Cells[0].AddParagraph(currCycle.end.ToString(@"yyyy.MM.dd HH:mm:ss"));
              if (currSZO.Count > 1)
                row.Cells[0].MergeDown = currSZO.Count - 1;
            }

            row.Cells[2].AddParagraph(currSZO[k].tEnd.ToString(@"HH\:mm\:ss"));
          }
        }
        //Add Footer for Table
        title = doc.LastSection.AddParagraph();
        title.Format.Alignment = ParagraphAlignment.Right;
        title.Format.Font.Size = 12;
        title.Format.Font.Name = "TNR";
        title.Format.SpaceAfter = new Unit(10, UnitType.Millimeter);
        title.AddText(
          "Общее время работы SZO печи №" + (i + 1).ToString("D2") +
          ": " + totalTimeVDP.ToString(@"hh\:mm\:ss")
        );
        totalTime = totalTime.Add(totalTimeVDP);
      }

      title = doc.LastSection.AddParagraph();
      title.Format.Alignment = ParagraphAlignment.Left;
      title.Format.Font.Size = 12;
      title.Format.Font.Name = "TNR";
      title.Format.SpaceAfter = new Unit(10, UnitType.Millimeter);
      title.AddText("Общее время работы SZO: " + totalTime.ToString(@"%d\.hh\:mm\:ss"));

      Print(date, doc, "SZO");
    }

    public static void Print(DateTime time, Document doc, string type)
    {
      Directory.CreateDirectory(Directory.GetCurrentDirectory() + '/' + type);
      var file = Directory.GetCurrentDirectory() + '/' + type + '/' + time.ToString("yyyy-MM-dd") + ".pdf";
      if (File.Exists(file)) File.Delete(file);
      var pdfRenderer = new PdfDocumentRenderer(true) { Document = doc };
      pdfRenderer.RenderDocument();
      pdfRenderer.PdfDocument.Save(file);
    }












    /// <summary>
    /// EZFontResolver is a generic font resolver for PDFsharp.
    /// It implement IFontResolver internally.
    /// To use it, just pass your fonts as filename or byte[]
    /// in calls to AddFont.
    /// </summary>
    public class EZFontResolver : IFontResolver
    {
      EZFontResolver()
      { }

      /// <summary>
      /// Gets the one and only EZFontResolver object.
      /// </summary>
      public static EZFontResolver Get
      {
        get { return _singleton ?? (_singleton = new EZFontResolver()); }
      }
      private static EZFontResolver _singleton;

      /// <summary>
      /// Adds the font passing a filename.
      /// </summary>
      /// <param name="familyName">Name of the font family.</param>
      /// <param name="style">The style.</param>
      /// <param name="filename">The filename.</param>
      /// <param name="simulateBold">if set to <c>true</c> bold will be simulated.</param>
      /// <param name="simulateItalic">if set to <c>true</c> italic will be simulated.</param>
      /// <exception cref="Exception">
      /// Font file is too big.
      /// or
      /// Reading font file failed.
      /// </exception>
      public void AddFont(string familyName, XFontStyle style, string filename,
          bool simulateBold = false, bool simulateItalic = false)
      {
        using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
          var size = fs.Length;
          if (size > int.MaxValue)
            throw new Exception("Font file is too big.");
          var length = (int)size;
          var data = new byte[length];
          var read = fs.Read(data, 0, length);
          if (length != read)
            throw new Exception("Reading font file failed.");
          AddFont(familyName, style, data, simulateBold, simulateItalic);
        }
      }

      /// <summary>
      /// Adds the font passing a byte array containing the font.
      /// </summary>
      /// <param name="familyName">Name of the font family.</param>
      /// <param name="style">The style.</param>
      /// <param name="data">The data.</param>
      /// <param name="simulateBold">if set to <c>true</c> bold will be simulated.</param>
      /// <param name="simulateItalic">if set to <c>true</c> italic will be simulated.</param>
      public void AddFont(string familyName, XFontStyle style, byte[] data,
          bool simulateBold = false, bool simulateItalic = false)
      {
        // Add the font as we get it.
        AddFontHelper(familyName, style, data, false, false);

        // If the font is not bold and bold simulation is requested, add that, too.
        if (simulateBold && (style & XFontStyle.Bold) == 0)
        {
          AddFontHelper(familyName, style | XFontStyle.Bold, data, true, false);
        }

        // Same for italic.
        if (simulateItalic && (style & XFontStyle.Italic) == 0)
        {
          AddFontHelper(familyName, style | XFontStyle.Italic, data, false, true);
        }

        // Same for bold and italic.
        if (simulateBold && (style & XFontStyle.Bold) == 0 &&
            simulateItalic && (style & XFontStyle.Italic) == 0)
        {
          AddFontHelper(familyName, style | XFontStyle.BoldItalic, data, true, true);
        }
      }

      void AddFontHelper(string familyName, XFontStyle style, byte[] data, bool simulateBold, bool simulateItalic)
      {
        // Currently we do not need FamilyName and Style.
        // FaceName is a combination of FamilyName and Style.
        var fi = new EZFontInfo
        {
          //FamilyName = familyName,
          FaceName = familyName.ToLower(),
          //Style = style,
          Data = data,
          SimulateBold = simulateBold,
          SimulateItalic = simulateItalic
        };
        if ((style & XFontStyle.Bold) != 0)
        {
          // TODO Create helper method to prevent having duplicate string literals?
          fi.FaceName += "|b";
        }
        if ((style & XFontStyle.Italic) != 0)
        {
          fi.FaceName += "|i";
        }

        // Check if we already have this font.
        var test = GetFont(fi.FaceName);
        if (test != null)
          throw new Exception("Font " + familyName + " with this style was already registered.");

        _fonts.Add(fi.FaceName.ToLower(), fi);
      }

      #region IFontResolver
      public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
      {
        string faceName = familyName.ToLower() +
            (isBold ? "|b" : "") +
            (isItalic ? "|i" : "");
        EZFontInfo item;
        if (_fonts.TryGetValue(faceName, out item))
        {
          var result = new FontResolverInfo(item.FaceName, item.SimulateBold, item.SimulateItalic);
          return result;
        }
        return null;
      }

      public byte[] GetFont(string faceName)
      {
        EZFontInfo item;
        if (_fonts.TryGetValue(faceName, out item))
        {
          return item.Data;
        }
        return null;
      }
      #endregion

      private readonly Dictionary<string, EZFontInfo> _fonts = new Dictionary<string, EZFontInfo>();

      struct EZFontInfo
      {
        //internal string FamilyName;
        internal string FaceName;
        //internal XFontStyle Style;
        internal byte[] Data;
        internal bool SimulateBold;
        internal bool SimulateItalic;
      }
    }
  }
}
