using FLY.Thick.FilmCasting.UI.DbViewer.Db;
using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;
using Misc;
using OfficeOpenXml;
using OfficeOpenXml.Drawing;
using OfficeOpenXml.Drawing.Chart;
using OfficeOpenXml.Table;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace FLY.Thick.FilmCasting.UI.DbViewer.Core
{
    public class ExcelOuput : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public double Progress {
            get {
                if (TotalRow > 0)
                {
                    if (CurrRow < TotalRow)
                    {
                        return 1.0 * CurrRow / TotalRow;
                    }
                    else
                    {
                        return 1;
                    }
                }
                else {
                    return 1;
                }
            }
        }
        public string Msg { get; private set; }

        protected int TotalRow { get; private set; } = 1;
        protected int CurrRow { get; private set; }
        const int CurrRowGrowUpStep = 500;
        public async Task SaveToXlsx(string filepath, DbProfilePack profilePack)
        {
            await SaveToXlsxNoTemplate(filepath, profilePack);
        }

        /// <summary>
        /// 没有模板导出数据
        /// </summary>
        /// <param name="filepath"></param>
        async Task SaveToXlsxNoTemplate(string filepath, DbProfilePack profilePack)
        {
            await Task.Run(() =>
            {

                using (ExcelPackage p = new ExcelPackage(new FileInfo(filepath)))
                {
                    CurrRowInit(profilePack.ScanDatas.Count());
                    
                    SaveToXlsxThk(p, profilePack);

                    Msg = "写入文件";
                    p.Save();

                }
            });
        }


        ExcelWorksheet GetSheet(ExcelPackage p, string sheet_name)
        {

            ExcelWorksheet sheet = p.Workbook.Worksheets[sheet_name];
            if (sheet == null)
            {
                sheet = p.Workbook.Worksheets.Add(sheet_name);
            }
            return sheet;
        }



        void ToSheet(ExcelWorksheet sheet, DataTable dataTable)
        {
            int from_row = 1;
            int row = from_row;
            //添加标题
            for (int i = 0; i < dataTable.Columns.Count; i++)
            {
                int col = i + 1;
                sheet.Cells[row, col].Value = dataTable.Columns[i].ColumnName;
                //格式
                sheet.Column(col).Style.Numberformat.Format = dataTable.Columns[i].Caption;
            }

            row++;
            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                for (int j = 0; j < dataTable.Columns.Count; j++)
                {
                    int col = j + 1;
                    sheet.Cells[row, col].Value = dataTable.Rows[i][j];
                }
                row++;
            }

            int colcnt = dataTable.Columns.Count;
            int rowcnt = dataTable.Rows.Count;
            var range = sheet.Cells[from_row, 1, from_row + rowcnt, colcnt];

            var tbl = sheet.Tables.Add(range, dataTable.TableName);
            tbl.TableStyle = TableStyles.Medium9;
            sheet.Cells[sheet.Dimension.Address].AutoFitColumns();
        }

        void SaveToXlsxThk(ExcelPackage p, DbProfilePack profilePack)
        {
            if (profilePack.ScanDatas == null || profilePack.ScanDatas.Count() == 0)
                return;//没有数据

            Msg = "导出扫描数据记录";
            int boltCnt = 0;
            int sampleCnt = 0;
            {
                var scanData = profilePack.ScanDatas.Last();
                boltCnt = scanData.Thicks.Count();
                if (scanData.SampleADs != null && scanData.SampleADs.Count() > 0)
                    sampleCnt = scanData.SampleADs.Count();
            }

            ExcelWorksheet sheet = GetSheet(p, "扫描数据");

            DataTable dataTable = new DataTable("table_thk");
            dataTable.Columns.Add(new DataColumn() { ColumnName = "开始时间", DataType = typeof(double), Caption = "yyyy-MM-dd HH:mm:ss" });
            dataTable.Columns.Add(new DataColumn() { ColumnName = "结束时间", DataType = typeof(double), Caption = "HH:mm:ss" });
            dataTable.Columns.Add(new DataColumn() { ColumnName = "目标值", DataType = typeof(double), Caption = "0.00" });
            dataTable.Columns.Add(new DataColumn() { ColumnName = "规格线%", DataType = typeof(double), Caption = "0.0" });
            dataTable.Columns.Add(new DataColumn() { ColumnName = "斜率补偿", DataType = typeof(double), Caption = "0.000" });
            dataTable.Columns.Add(new DataColumn() { ColumnName = "平移补偿", DataType = typeof(double), Caption = "0.00" });

            dataTable.Columns.Add(new DataColumn() { ColumnName = "纵向位置(m)", DataType = typeof(double), Caption = "0.0" });
            dataTable.Columns.Add(new DataColumn() { ColumnName = "线速度(m/min)", DataType = typeof(double), Caption = "0.0" });
            dataTable.Columns.Add(new DataColumn() { ColumnName = "膜宽度(mm)", DataType = typeof(double), Caption = "0" });
            
            dataTable.Columns.Add(new DataColumn() { ColumnName = "平均值(um)", DataType = typeof(double), Caption = "0.00" });
            dataTable.Columns.Add(new DataColumn() { ColumnName = "2σ(%)", DataType = typeof(double), Caption = "0.0" });

            for (int i = 0; i < boltCnt; i++)
                dataTable.Columns.Add(new DataColumn() { ColumnName = $"分区{i + 1}(um)", DataType = typeof(double), Caption = "0.0" });

            for (int i = 0; i < sampleCnt; i++)
                dataTable.Columns.Add(new DataColumn() { ColumnName = $"样品{i}AD", DataType = typeof(double), Caption = "0" });


            CurrRowGrowUpReady();
            for (int i = 0; i < profilePack.ScanDatas.Count(); i++)
            {
                var scanData = profilePack.ScanDatas[i];

                var dataRow = dataTable.NewRow();

                dataRow["开始时间"] = scanData.Time.ToOADate();
                dataRow["结束时间"] = scanData.EndTime.ToOADate();
                dataRow["目标值"] = scanData.Target;
                dataRow["规格线%"] = scanData.TolerancePercent * 100.0;
                dataRow["斜率补偿"] = scanData.K;
                dataRow["平移补偿"] = scanData.B;
                dataRow["纵向位置(m)"] = scanData.FilmPosition;
                dataRow["线速度(m/min)"] = scanData.FilmVelocity;
                dataRow["膜宽度(mm)"] = scanData.FilmWidth;

                double avg = scanData.Thicks.AverageNoNull();
                double sigma = scanData.Thicks.Sigma();
                dataRow["平均值(um)"] = avg;
                if (avg > 0)
                {
                    double sigma2p = sigma / avg * 2 * 100;
                    dataRow["2σ(%)"] = sigma2p;

                    for (int j = 0; j < boltCnt && j < scanData.Thicks.Count(); j++)
                    {
                        var v = scanData.Thicks[j];
                        if (!double.IsNaN(v))
                        {
                            dataRow[$"分区{j + 1}(um)"] = v;
                        }
                    }
                }
                if(scanData.SampleADs!=null )
                for (int j = 0; j < sampleCnt && j< scanData.SampleADs.Count(); j++)
                    dataRow[$"样品{j}AD"] = scanData.SampleADs[j];

                dataTable.Rows.Add(dataRow);
                CurrRowGrowUping(i);
            }
            CurrRowGrowUpFinish(profilePack.ScanDatas.Count());

            ToSheet(sheet, dataTable);
        }

        void CurrRowInit(int totalRow)
        {
            TotalRow = totalRow;
            CurrRow = 0;
        }
        int _currRow = 0;
        void CurrRowGrowUpReady()
        {
            _currRow = CurrRow;
        }
        void CurrRowGrowUping(int i)
        {
            if (i % CurrRowGrowUpStep == 0)
                CurrRow = _currRow + i;
        }
        void CurrRowGrowUpFinish(int cnt)
        {
            CurrRow = _currRow + cnt;
        }

    }
}
