using Syncfusion.DocIO.DLS;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using Vinno.vCloud.ReportGenerator;
using Vinno.vCloud.Protocol.Initializers;
using Vinno.vCloud.Report.Models;
using PdfSharp.Pdf;
using PdfSharp.Drawing;

namespace ReportConverter
{
    class Program
    {
        private static string _language = string.Empty;
        /// <summary>
        /// main function
        /// </summary>
        /// <param name="args">
        /// 0:"AddReportServer" 1:jsonPath 2:outFolder 3:StorageUrl 4:StorageType
        /// 1:"Share" 1:jsonPath 2:language 3:StorageUrl 4:StorageType
        /// 2:"PackagingPdf" 1:jsonPath 2:language 3:StorageUrl 4:StorageType
        /// </param>
        static void Main(string[] args)
        {
            if (args == null || args.Length < 2) return;
            try
            {
                new InitializeLanguage();
                ClientTagsInitializer.Initialize();
                if (string.IsNullOrEmpty(args[0])) return;
                if (args[0].Equals("AddReportServer"))
                {
                    ReportInfo ri = ReportJsonSerializer.DeSerialize($"{args[1]}.json");
                    //get image from stroge server
                    new GetReportInfo(args[3], GetStorageType(args)).GetReportInfoAsync(ri).Wait(60000);
                    //translate gender
                    new GenderTranslater().TranslateGender(ri);
                    var wordDocument = ReportWordDocumentManager.GetGenerateWordDocument(ri);
                    if (wordDocument != null)
                    {
                        Image[] images = ((ReportWordDocument)wordDocument).RenderAsImages(ImageType.Bitmap);
                        string imagePath = string.Empty;
                        for (int i = 0; i < images.Length; i++)
                        {
                            imagePath = Path.Combine(args[2], $"{i}.jpg");
                            images[i]?.Save(imagePath, ImageFormat.Jpeg);
                            Console.WriteLine(imagePath);
                        }
                        //Closes the document
                        ((ReportWordDocument)wordDocument).Close();
                    }
                }
                else if (args[0].Equals("Share"))
                {
                    _language = args[2]?.ToLower() ?? string.Empty;
                    ReportInfo ri = ReportJsonSerializer.DeSerialize($"{args[1]}.json");
                    #region set default tmplate
                    if (ri.Template == null)
                    {
                        string tmpPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DefaultReportTemplate", "Default_en.json");
                        if (_language.StartsWith("zh"))
                        {
                            tmpPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DefaultReportTemplate", "Default.json");
                        }
                        ri.Template = new ReportTemplateJsonSerializer().DeSerializeJson(File.ReadAllText(tmpPath));
                    }
                    #endregion
                    //get image from stroge server
                    new GetReportInfo(args[3], GetStorageType(args)).GetReportInfoAsync(ri).Wait(60000);
                    //translate gender
                    new GenderTranslater().TranslateGender(ri);
                    #region write images
                    if (args.Length > 5)
                    {
                        var scaleRatio = Convert.ToSingle(args[5]);
                        ScaleTemplateSizeDouble(ri.Template, scaleRatio);
                    }

                    var wordDocument = ReportWordDocumentManager.GetGenerateWordDocument(ri);
                    if (wordDocument != null)
                    {
                        Image[] images = ((ReportWordDocument)wordDocument).RenderAsImages(ImageType.Bitmap);
                        string imagePath = string.Empty;
                        for (int i = 0; i < images.Length; i++)
                        {
                            imagePath = $"{args[1]}_{i}.jpg";
                            images[i]?.Save(imagePath, ImageFormat.Jpeg);
                            Console.WriteLine(imagePath);
                        }
                        //Closes the document
                        ((ReportWordDocument)wordDocument).Close();
                    }
                    #endregion
                }
                else if (args[0].Equals("Packaging"))
                {
                    if (File.Exists($"{args[1]}.pdf")) { return; }
                    ReportInfo ri = ReportJsonSerializer.DeSerialize($"{args[1]}.json");
                    //get image from stroge server
                    new GetReportInfo(args[3], GetStorageType(args)).GetReportInfoAsync(ri).Wait(60000);
                    //translate gender
                    new GenderTranslater().TranslateGender(ri);
                    using (var wordDocument = ReportWordDocumentManager.GetGenerateWordDocument(ri))
                    {
                        if (wordDocument != null)
                        {
                            Image[] images = ((ReportWordDocument)wordDocument).RenderAsImages(ImageType.Bitmap);
                            string imagePath = string.Empty;
                            using (PdfDocument doc = new PdfDocument())
                            {
                                for (int i = 0; i < images.Length; i++)
                                {
                                    using (var imageStream = ImageToByteArray(images[i]))
                                    {
                                        using (XImage img = XImage.FromStream(imageStream))
                                        {
                                            var newPage = new PdfPage();
                                            newPage.Height = new XUnit(img.PointHeight);
                                            newPage.Width = new XUnit(img.PointWidth);
                                            doc.Pages.Add(newPage);
                                            using (XGraphics xgr = XGraphics.FromPdfPage(doc.Pages[i]))
                                            {
                                                xgr.DrawImage(img, 0, 0);
                                            }
                                        }
                                    }
                                }
                                doc.Save(Path.Combine(args[2], $"{args[1]}.pdf"));
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                string errPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Error");
                if (!Directory.Exists(errPath)) Directory.CreateDirectory(errPath);
                File.AppendAllText(Path.Combine(errPath, $"{DateTime.Now.ToString("yyyyMMdd_HHmmss") + Guid.NewGuid().ToString("N")}.log"), e.ToString());
            }
        }

        private static Stream ImageToByteArray(Image img)
        {
            var ms = new MemoryStream();
            img.Save(ms, ImageFormat.Jpeg);
            return ms;
        }

        private static void ScaleTemplateSizeDouble(Vinno.vCloud.Report.Interfaces.IReportTemplateDocument template, float scaleRatio)
        {
            template.PageSize = new Vinno.vCloud.Report.Interfaces.RTPageSize(template.PageSize.Width * scaleRatio, template.PageSize.Height * scaleRatio);
            ScaleRTThicknessDouble(template.PagePadding, scaleRatio);
            template.HeaderDistance *= scaleRatio;
            template.FooterDistance *= scaleRatio;

            ScaleElementSizeDouble(template.Blocks, scaleRatio);
            ScaleElementSizeDouble(template.Header, scaleRatio);
            ScaleElementSizeDouble(template.Footer, scaleRatio);
        }
        private static void ScaleElementSizeDouble(System.Collections.Generic.IReadOnlyList<Vinno.vCloud.Report.Interfaces.IElement> elements, float scaleRatio)
        {
            foreach (var element in elements)
            {
                ScaleRTThicknessDouble(element.Margin, scaleRatio);

                if (element is InputImageList iptImgElement)
                {
                    iptImgElement.ImageWidth *= scaleRatio;
                    iptImgElement.ImageHeight *= scaleRatio;
                }
                else if (element is Vinno.vCloud.Report.Interfaces.ITextElement txtElement)
                {
                    txtElement.LineWidth *= scaleRatio;
                    txtElement.FontSize *= scaleRatio;
                }
                else if (element is Vinno.vCloud.Report.Interfaces.IImage imageEle)
                {
                    imageEle.Width *= scaleRatio;
                    imageEle.Height *= scaleRatio;
                }
                else if (element is Vinno.vCloud.Report.Interfaces.ILine lineEle)
                {
                    lineEle.Width *= scaleRatio;
                }
                else if (element is Vinno.vCloud.Report.Interfaces.IGrid gridEle)
                {
                    foreach (var item in gridEle.ColumnDefinitions)
                    {
                        item.Width *= scaleRatio;
                    }
                    foreach (var item in gridEle.RowDefinitions)
                    {
                        item.Height *= scaleRatio;
                    }
                    foreach (var item in gridEle.Cells.Values)
                    {
                        item.Borders.Left.Thickness *= scaleRatio;
                        ScaleRTThicknessDouble(item.Margin, scaleRatio);
                        ScaleElementSizeDouble(item.Blocks, scaleRatio);
                    }
                }
                else if (element is Vinno.vCloud.Report.Interfaces.IBlockElement blockEle)
                {
                    ScaleElementSizeDouble(blockEle.Elements, scaleRatio);
                }
            }
        }
        private static void ScaleRTThicknessDouble(Vinno.vCloud.Report.Interfaces.RTThickness thickness, float scaleRatio)
        {
            thickness.Left *= scaleRatio;
            thickness.Right *= scaleRatio;
            thickness.Top *= scaleRatio;
            thickness.Bottom *= scaleRatio;
        }

        /// <summary>
        /// 获取StorageType类型:0.默认服务器,1.Ufile服务器
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private static int GetStorageType(string[] args)
        {
            int storageType = 0;
            if (args.Length >= 4)
            {
                var param = args[4];
                int.TryParse(param, out storageType);
            }
            return storageType;
        }

        private static string GetFont(string fontName)
        {
            var fontCollection = new InstalledFontCollection();
            var fontFamilies = fontCollection.Families.Where(f => !string.IsNullOrEmpty(f.Name)).ToList();
            var fontFamily =
                fontFamilies.FirstOrDefault(f => f.GetName(2052) == fontName || f.GetName(1033) == fontName);
            if (fontFamily == null)
            {
                return fontFamilies.FirstOrDefault(a => a.GetName(1033) == "Microsoft YaHei")?.Name;
            }

            return fontFamily.Name;
        }
    }
}