using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;
using OfficeOpenXml;
using OfficeOpenXml.Drawing;
using OfficeOpenXml.Drawing.Chart;
using OfficeOpenXml.Table;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using static OfficeOpenXml.Drawing.ExcelDrawing;
using FontStyle = System.Drawing.FontStyle;

namespace WSDDBBrowser.Core
{

    public class ExcelOuput
    {
        public IEnumerable<FrameworkElement> charts;
        public async void SaveToXlsx(string filepath)
        {
            string srcpath = "报表模板.xlsx";
            //复制 电池报表模板.xlsx 模板 到目标位置
            if (!File.Exists(srcpath))
            {
                await ((MetroWindow)Application.Current.MainWindow).ShowMessageAsync(
                    "出错",
                    $"不能找到 {srcpath}");
                return;
            }
            var controller = await ((MetroWindow)Application.Current.MainWindow).ShowProgressAsync("请等待...", "开始导出",
                settings: new MetroDialogSettings()
                {
                    NegativeButtonText = "停止",
                    AnimateShow = false,
                    AnimateHide = false,

                });
            //controller.SetCancelable(true);
            controller.SetIndeterminate();

            await Task.Run(() =>
            {

                File.Copy(srcpath, filepath, true);

                using (ExcelPackage p = new ExcelPackage(new FileInfo(filepath)))
                {
                    if (DBViewerModel.Instance.CurrProcess.HasSBData)
                    {
                        SaveToXlsxMonitorInfo(p);
                        SaveToXlsxDeviceData(p);
                    }
                    else
                    {
                        p.Workbook.Worksheets.Delete("温控总体描述");
                        p.Workbook.Worksheets.Delete("温控记录");
                    }
                    if (DBViewerModel.Instance.CurrProcess.HasTGData)
                    {
                        charts.ElementAt(0).Invoke(() =>
                        {
                            SaveToXlsxThicknessInfo(p);
                        });
                    }
                    else
                    {
                        p.Workbook.Worksheets.Delete("厚度总体描述");
                    }
                    p.Save();
                }
            });

            await controller.CloseAsync();

            await ((MetroWindow)Application.Current.MainWindow).ShowMessageAsync("输出成功",
                filepath);
        }


        #region 厚度总体描述
        void SaveToXlsxThicknessInfo(ExcelPackage p)
        {
            var ws = p.Workbook.Worksheets["厚度总体描述"];//获取worksheet

            var process = DBViewerModel.Instance.CurrProcess;
            ws.Cells["B2"].Value = process.OrderNo;
            ws.Cells["B4"].Value = process.ProjectNo;
            ws.Cells["F4"].Value = process.TechnologyNo;


            ws.Cells["B6"].Value = process.BeginTime;
            ws.Cells["F6"].Value = process.EndTime;
            ws.Cells["B7"].Value = process.TotalLen;
            ws.Cells["F7"].Value = DBViewerModel.Instance.TGProcessPacks.Sum(_p => _p.Numbers.Count());



            //图片插入
            //找到第1页的图片
            List<ExcelPicture> pics = new List<ExcelPicture>();
            pics.AddRange(from draw in ws.Drawings where draw is ExcelPicture select draw as ExcelPicture);
            ws.Drawings.Clear();

            //List<Rect>[] page_rects = new List<Rect>[2] {
            //    new List<Rect>{
            //        new Rect(){X =0, Y = 266, Height = 470, Width =932},
            //        new Rect(){X =0, Y = 769, Height = 470, Width =932}
            //    },
            //    new List<Rect>{
            //        new Rect(){X =0, Y = 1649, Height = 470, Width =932},
            //        new Rect(){X =0, Y = 2146, Height = 470, Width =932},
            //        new Rect(){X =0, Y = 2646, Height = 470, Width =932}
            //    }
            //};
            //List<ExcelPicRect>[] page_rects = new List<ExcelPicRect>[2] {
            //    new List<ExcelPicRect>(),
            //    new List<ExcelPicRect>()
            //};
            List<ExcelPicRect>[] page_rects = new List<ExcelPicRect>[2] {
                new List<ExcelPicRect>{new ExcelPicRect(){Row=10},new ExcelPicRect(){Row=35} },
                new List<ExcelPicRect>{new ExcelPicRect(){Row=79},new ExcelPicRect(){Row=104},new ExcelPicRect(){Row=129} },
            };
            //Regex regex = new Regex(@"Pg(\d)Pic(\d)");

            //foreach (var pic in pics)
            //{
            //    //pic.Name
            //    var match = regex.Match(pic.Name);
            //    if (match.Success)
            //    {
            //        int page = int.Parse(match.Groups[1].Value);
            //        int pic_no = int.Parse(match.Groups[2].Value);
            //        if (page < page_rects.Count())
            //        {
            //            while (pic_no >= page_rects[page].Count())
            //            {
            //                page_rects[page].Add(null);
            //            }
            //            page_rects[page][pic_no] = new ExcelPicRect()
            //            {
            //                Column = pic.From.Column,
            //                ColumnOff = pic.From.ColumnOff,
            //                Row = pic.From.Row,
            //                RowOff = pic.From.RowOff
            //            };
            //        }
            //    }
            //}

            for (int i = 0; i < charts.Count(); i++)
            {
                FrameworkElement visual = charts.ElementAt(i);

                var bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32);
                bitmap.Render(visual);

                System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(bitmap.PixelWidth, bitmap.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

                System.Drawing.Imaging.BitmapData data =
                    bmp.LockBits(
                        new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size),
                        System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

                bitmap.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
                bmp.UnlockBits(data);

                ExcelPicture pic = ws.Drawings.AddPicture("pic" + (i).ToString(), bmp);

                //if (i < page_rects[0].Count())
                //{
                //    pic.SetPosition((int)page_rects[0][i].Top, (int)page_rects[0][i].Left);
                //    //
                //}
                //else
                //{
                //    int i2 = i - page_rects[0].Count();
                //    int page = i2 / page_rects[1].Count() + 1;
                //    int index = i2 % page_rects[1].Count();
                //    int top = (int)((page_rects[1][index].Top - page_rects[1][0].Top) + page_rects[1][0].Top * page);
                //    pic.SetPosition(top, 0);

                //}
                //pic.SetSize(82);

                if (i < page_rects[0].Count())
                {
                    pic.SetPosition(page_rects[0][i].Row, 0, 0, 0);
                    //
                }
                else
                {
                    int i2 = i - page_rects[0].Count();
                    int page = i2 / page_rects[1].Count() + 1;
                    int index = i2 % page_rects[1].Count();
                    int top = (int)((page_rects[1][index].Row - page_rects[1][0].Row) + page_rects[1][0].Row * page);
                    pic.SetPosition(top, 0, 0, 0);
                }
                pic.SetSize(932, 470);
            }

        }
        #endregion

        #region 总体描述
        void SaveToXlsxMonitorInfo(ExcelPackage p)
        {
            var ws = p.Workbook.Worksheets["温控总体描述"];//获取worksheet

            var process = DBViewerModel.Instance.CurrProcess;

            //订单号
            ws.Cells["B2"].Value = process.OrderNo;
            //项目号
            ws.Cells["B3"].Value = process.ProjectNo;
            //工艺号
            ws.Cells["B4"].Value = process.TechnologyNo;
            //开始时间
            ws.Cells["B5"].Value = process.BeginTime.ToOADate();
            //结束时间
            ws.Cells["E5"].Value = process.EndTime.ToOADate();
            //记录码数
            ws.Cells["B6"].Value = process.TotalLen;
            //备注
            ws.Cells["B7"].Value = DBViewerModel.Instance.SBProcessPack.Process.cRemarks;


            SaveToXlsxInfo_username(ws, 12, out int end_row);
            SaveToXlsxInfo_number(ws, end_row + 3, out end_row);
            SaveToXlsxInfo_technologyItem(ws, end_row + 3, out end_row);


        }
        void SaveToXlsxInfo_username(ExcelWorksheet sheet, int header_row, out int end_row)
        {
            //标题
            sheet.Cells[header_row, 1].Value = "用户名";
            sheet.Cells[header_row, 2].Value = "开始时间";
            sheet.Cells[header_row, 3].Value = "结束时间";
            var users = DBViewerModel.Instance.SBProcessPack.Users;
            //内容
            int row = header_row + 1;
            for (int i = 0; i < users.Count(); i++)
            {
                var user = users[i];
                sheet.Cells[row, 1].Value = user.cUserName;
                sheet.Cells[row, 2].Value = ((DateTime)user.tBeginTime).ToOADate();
                sheet.Cells[row, 3].Value = ((DateTime)user.tEndTime).ToOADate();
                row++;
            }

            //设置格式
            var range = sheet.Cells[header_row + 1, 1, row, 1];
            range.Style.Numberformat.Format = "0";

            range = sheet.Cells[header_row + 1, 2, row, 3];
            range.Style.Numberformat.Format = "MM-dd HH:mm";

            //设置为表格
            range = sheet.Cells[header_row, 1, row, 3];
            var tbl = sheet.Tables.Add(range, "table_username");
            tbl.TableStyle = TableStyles.Medium9;
            sheet.Cells[sheet.Dimension.Address].AutoFitColumns();

            end_row = row;
        }

        void SaveToXlsxInfo_number(ExcelWorksheet sheet, int header_row, out int end_row)
        {
            //标题
            sheet.Cells[header_row, 1].Value = "生产卷号";
            sheet.Cells[header_row, 2].Value = "开始时间";
            sheet.Cells[header_row, 3].Value = "结束时间";
            sheet.Cells[header_row, 4].Value = "开始码数";
            sheet.Cells[header_row, 5].Value = "结束码数";
            sheet.Cells[header_row, 6].Value = "总码数";
            sheet.Cells[header_row, 7].Value = "实际码数";

            var numbers = DBViewerModel.Instance.SBProcessPack.Numbers;
            //内容
            int row = header_row + 1;
            for (int i = 0; i < numbers.Count(); i++)
            {
                var dB_Number = numbers[i];
                sheet.Cells[row, 1].Value = dB_Number.cNumber;
                sheet.Cells[row, 2].Value = ((DateTime)dB_Number.tBeginTime).ToOADate();
                sheet.Cells[row, 3].Value = ((DateTime)dB_Number.tEndTime).ToOADate();
                sheet.Cells[row, 4].Value = dB_Number.nBeginLen;
                sheet.Cells[row, 5].Value = dB_Number.nEndLen;
                sheet.Cells[row, 6].Value = dB_Number.nEndLen - dB_Number.nBeginLen;
                sheet.Cells[row, 7].Value = dB_Number.nActiveLen;
                row++;
            }

            //设置格式
            var range = sheet.Cells[header_row + 1, 1, row, 1];
            range.Style.Numberformat.Format = "0";

            range = sheet.Cells[header_row + 1, 2, row, 3];
            range.Style.Numberformat.Format = "MM-dd HH:mm";

            range = sheet.Cells[header_row + 1, 4, row, 7];
            range.Style.Numberformat.Format = "0.00";


            //设置为表格
            range = sheet.Cells[header_row, 1, row, 7];
            var tbl = sheet.Tables.Add(range, "table_number");
            tbl.TableStyle = TableStyles.Medium10;
            sheet.Cells[sheet.Dimension.Address].AutoFitColumns();

            end_row = row;
        }

        void SaveToXlsxInfo_technologyItem(ExcelWorksheet sheet, int header_row, out int end_row)
        {
            //标题
            sheet.Cells[header_row, 1].Value = "设备ID";
            sheet.Cells[header_row, 2].Value = "设备名称";
            sheet.Cells[header_row, 3].Value = "目标值";
            sheet.Cells[header_row, 4].Value = "公差";
            sheet.Cells[header_row, 5].Value = "平均值";
            sheet.Cells[header_row, 6].Value = "最大值";
            sheet.Cells[header_row, 7].Value = "最小值";
            sheet.Cells[header_row, 8].Value = "是否超限";

            var recordCollections = DBViewerModel.Instance.RecordCollections;
            //内容
            int row = header_row + 1;
            for (int i = 0; i < recordCollections.Count(); i++)
            {
                var recordCollection = recordCollections[i];
                sheet.Cells[row, 1].Value = recordCollection.DeviceID;
                sheet.Cells[row, 2].Value = recordCollection.DeviceName;
                sheet.Cells[row, 3].Value = recordCollection.Target;
                sheet.Cells[row, 4].Value = recordCollection.Tolerance;



                sheet.Cells[row, 5].Value = recordCollection.Average;
                sheet.Cells[row, 6].Value = recordCollection.Max;
                sheet.Cells[row, 7].Value = recordCollection.Min;
                sheet.Cells[row, 8].Value = recordCollection.IsError;

                row++;
            }

            //设置格式
            var range = sheet.Cells[header_row + 1, 1, row, 2];
            range.Style.Numberformat.Format = "0";

            range = sheet.Cells[header_row + 1, 3, row, 7];
            range.Style.Numberformat.Format = "0.0";


            //设置为表格
            range = sheet.Cells[header_row, 1, row, 8];
            var tbl = sheet.Tables.Add(range, "table_technologyItem");
            tbl.TableStyle = TableStyles.Medium11;
            sheet.Cells[sheet.Dimension.Address].AutoFitColumns();

            end_row = row;
        }

        #endregion

        void SaveToXlsxDeviceData(ExcelPackage p)
        {
            var sheet = p.Workbook.Worksheets["温控记录"];//获取worksheet

            var recordCollections = DBViewerModel.Instance.RecordCollections;
            int header_row = 1;
            //标题
            sheet.Cells[header_row, 1].Value = "卷号";
            sheet.Cells[header_row, 2].Value = "时间";
            sheet.Cells[header_row, 3].Value = "码数";
            for (int i = 0; i < recordCollections.Count(); i++)
            {
                sheet.Cells[header_row, 4 + i].Value = recordCollections[i].DeviceName;
            }

            //内容
            int row = header_row + 1;
            int end_row = row;
            for (int i = 0; i < recordCollections.Count(); i++)
            {
                var recordCollection = recordCollections[i];

                var records = recordCollection.Values;
                for (int j = 0; j < records.Count(); j++)
                {
                    var record = records.ElementAt(j);
                    if (i == 0)
                    {
                        var db_number = DBViewerModel.Instance.SBProcessPack.Numbers.Find(
                            _db_number => record.Time >= _db_number.tBeginTime  && record.Time<= _db_number.tEndTime);
                        if (db_number != null)
                        {
                            sheet.Cells[row + j, 1].Value = db_number.cNumber;
                        }
                        sheet.Cells[row + j, 2].Value = record.Time.ToOADate();
                        sheet.Cells[row + j, 3].Value = record.ProcessLen;
                    }
                    sheet.Cells[row + j, 4 + i].Value = record.MValue;
                }
                if (end_row < row + records.Count())
                    end_row = row + records.Count();
            }


            //设置格式
            sheet.Column(1).Style.Numberformat.Format = "0";
            sheet.Column(2).Style.Numberformat.Format = "MM-dd HH:mm";
            sheet.Column(3).Style.Numberformat.Format = "0.00";
            for (int i = 0; i < recordCollections.Count(); i++)
            {
                sheet.Column(4 + i).Style.Numberformat.Format = "0.0";
            }



            //设置为表格
            var range = sheet.Cells[header_row, 1, end_row, 4 + recordCollections.Count() - 1];
            var tbl = sheet.Tables.Add(range, "table_record");
            tbl.TableStyle = TableStyles.Medium12;
            sheet.Cells[sheet.Dimension.Address].AutoFitColumns();

        }



    }

    public class ExcelPicRect
    {
        public int Column { get; set; }
        public int Row { get; set; }
        //
        // 摘要:
        //     Column Offset EMU units 1cm = 1/360000 1US inch = 1/914400 1pixel = 1/9525
        public int ColumnOff { get; set; }
        //
        // 摘要:
        //     Row Offset EMU units 1cm = 1/360000 1US inch = 1/914400 1pixel = 1/9525
        public int RowOff { get; set; }
    }

    public class EPPlusPicture
    {
        public static void CreatePicture(ExcelWorksheet worksheet, string name, Image image, int firstColumn, int lastColumn, int firstRow, int lastRow, int defaultOffsetPixels)
        {
            int columnWidth = GetWidthInPixels(worksheet.Cells[firstRow, firstColumn]);
            int rowHeight = GetHeightInPixels(worksheet.Cells[firstRow, firstColumn]);

            int totalColumnWidth = columnWidth * (lastColumn - firstColumn + 1);
            int totalRowHeight = rowHeight * (lastRow - firstRow + 1);
            double cellAspectRatio = Convert.ToDouble(totalColumnWidth) / Convert.ToDouble(totalRowHeight);

            int imageWidth = image.Width;
            int imageHeight = image.Height;
            double imageAspectRatio = Convert.ToDouble(imageWidth) / Convert.ToDouble(imageHeight);

            int pixelWidth;
            int pixelHeight;
            if (imageAspectRatio > cellAspectRatio)
            {
                pixelWidth = totalColumnWidth - defaultOffsetPixels * 2;
                pixelHeight = pixelWidth * imageHeight / imageWidth;
            }
            else
            {
                pixelHeight = totalRowHeight - defaultOffsetPixels * 2;
                pixelWidth = pixelHeight * imageWidth / imageHeight;
            }

            int rowOffsetPixels = (totalRowHeight - pixelHeight) / 2;
            int columnOffsetPixels = (totalColumnWidth - pixelWidth) / 2;

            int rowOffsetCount = 0;
            int columnOffsetCount = 0;

            if (rowOffsetPixels > rowHeight)
            {
                rowOffsetCount = (int)Math.Floor(Convert.ToDouble(rowOffsetPixels) / Convert.ToDouble(rowHeight));
                rowOffsetPixels -= rowHeight * rowOffsetCount;
            }

            if (columnOffsetPixels > columnWidth)
            {
                columnOffsetCount = (int)Math.Floor(Convert.ToDouble(columnOffsetPixels) / Convert.ToDouble(columnWidth));
                columnOffsetPixels -= columnWidth * columnOffsetCount;
            }

            int row = firstRow + rowOffsetCount - 1;
            int column = firstColumn + columnOffsetCount - 1;

            ExcelPicture pic = worksheet.Drawings.AddPicture(name, image);
            pic.SetPosition(row, rowOffsetPixels, column, columnOffsetPixels);
            pic.SetSize(pixelWidth, pixelHeight);
        }

        public static int GetHeightInPixels(ExcelRange cell)
        {
            using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
            {
                float dpiY = graphics.DpiY;
                return (int)(cell.Worksheet.Row(cell.Start.Row).Height * (1 / 72.0) * dpiY);
            }
        }

        public static float MeasureString(string s, Font font)
        {
            using (var g = Graphics.FromHwnd(IntPtr.Zero))
            {
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                return g.MeasureString(s, font, int.MaxValue, StringFormat.GenericTypographic).Width;
            }
        }

        public static int GetWidthInPixels(ExcelRange cell)
        {
            double columnWidth = cell.Worksheet.Column(cell.Start.Column).Width;
            Font font = new Font(cell.Style.Font.Name, cell.Style.Font.Size, FontStyle.Regular);
            double pxBaseline = Math.Round(MeasureString("1234567890", font) / 10);
            return (int)(columnWidth * pxBaseline);
        }
    }
}
