using ryPrint;
using ryPrint.Mod;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace RyPrint
{
    /// <summary>
    /// 如果涉及到分页打印,切勿在PrintPage事件中多次实例化
    /// </summary>
    public class SmartPrint
    {
        private Hashtable dt_list = new Hashtable();
        /// <summary>
        /// 设置获取加载的模板
        /// </summary>
        public string Mod_Xml { get; set; } = "";
        private PrintDocument _Print_Doc = null;
        public SmartPrint(string mod_xml,PrintDocument Print_Doc)
        {
            Mod_Xml = mod_xml;
            Print_Doc.BeginPrint += Print_Doc_BeginPrint;
            Print_Doc.PrintPage += Print_Doc_PrintPage;           
            _Print_Doc = Print_Doc;
        }
        

        public SmartPrint(PrintDocument Print_Doc)
        {
            Print_Doc.BeginPrint += Print_Doc_BeginPrint;
            Print_Doc.PrintPage += Print_Doc_PrintPage;
            _Print_Doc = Print_Doc;
        }
        public SmartPrint()
        {
        }
        /// <summary>
        /// 显示打印预览窗口
        /// </summary>
        public void ShowPreviewForm()
        {
            if (!_Print_Doc.PrinterSettings.IsValid)
            { MessageBox.Show("当前打印机无效。请确认是否已安装打印机。","提示",MessageBoxButtons.OK,MessageBoxIcon.Information); return; }
            IsPreview = true;
            frmPrintPreview frm = new frmPrintPreview();
            frm._SmartPrint = this;
            frm.PrintDoc = _Print_Doc;
            frm.ShowDialog();
        }
        private void Print_Doc_PrintPage(object sender, PrintPageEventArgs e)
        {
            Print(Mod_Xml, e, IsPreview);
        }

        private void Print_Doc_BeginPrint(object sender, PrintEventArgs e)
        {
            StartPrint();
        }

        /// <summary>
        /// 左边距
        /// </summary>
        public int MarginLeft { get; set; } = 0;
        /// <summary>
        /// 顶部边距
        /// </summary>
        public int MarginTop { get; set; } = 0;
        /// <summary>
        /// 单位是否是英寸,如果false，则是毫米,默认false。
        /// </summary>
        public bool IsInch { get; set; } = false;
        /// <summary>
        /// 是否是预览
        /// </summary>
        public bool IsPreview { get; set; } = false;
        public string FontName { get; set; } = "黑体";
        private int _curPageIndex = 0;
        /// <summary>
        /// 获取或设置当前打印的是第几页,从0开始计数
        /// </summary>
        public int curPageIndex
        {
            get { return _curPageIndex; }
            set
            {
                if (value < 0) { _curPageIndex=0; }
                else { _curPageIndex= value; }
            }
        }
        private int _MaxPage = -1;
        /// <summary>
        /// 获取或设置当前最多打印到第几页,从0开始计数,-1表示打印到结束
        /// </summary>
        public int MaxPage
        {
            get { return _MaxPage; }
            set
            {
                if (value < 0) { _MaxPage = -1; }
                else { _MaxPage = value; }
            }
        }
        /// <summary>
        /// 设置纸张名称
        /// </summary>
        public string PaperName { get; set; } = "打印内容";
        /// <summary>
        /// 是否横向打印
        /// </summary>
        public bool Landscape { get; set; } = true;
        /// <summary>
        /// 是否打印多页,如果设为true,有多页文本,则打印多页,没有则打印一页。
        /// </summary>
        public bool PrintMorePages { get; set; } = true;
        public delegate void DataSetHandler(string DataSource,out DataTable ds);
        [Description("获取数据表时激发")]
        public event DataSetHandler OnDataSet;
        public void StartPrint()
        {
            //curPageIndex = 0;
            dt_list.Clear();
            ryCommon.Storage tStor_set = new ryCommon.Storage(Mod_Xml);
            tStor_set.SelectNode2("id", "set");
            double mmWidth = tStor_set.GetAttrValue("Width", 0d);
            double mmHeight = tStor_set.GetAttrValue("Height", 0d);
            PaperSize sPSize = new PaperSize(PaperName, (int)RySet.MMToInches(mmHeight * 100), (int)RySet.MMToInches(mmWidth * 100));//267为英寸转厘米为8厘米                                                                                                                                  //PaperSize sPSize = new PaperSize("快递单", (int)pixelsToInches(image.Width * 100), (int)pixelsToInches(image.Height * 100));
            if (!Landscape)
            {
                sPSize = new PaperSize(PaperName, (int)RySet.MMToInches(mmWidth * 100), (int)RySet.MMToInches(mmHeight * 100));//267为英寸转厘米为8厘米   
            }
            _Print_Doc.DefaultPageSettings.PaperSize = sPSize;
        }
        public void Print()
        {
            curPageIndex = 0;
            MaxPage = -1;
            IsPreview = false;
            _Print_Doc.PrinterSettings.FromPage = 0;
            _Print_Doc.Print();
        }
        /// <summary>
        /// 打印
        /// </summary>
        /// <param name="mod_xml">打印模板</param>
        /// <param name="e">打印参数</param>
        /// <param name="isPreview">是否是预览</param>
        public void Print(string mod_xml, PrintPageEventArgs e,bool isPreview)
        {
            try
            {
                e.Graphics.PageUnit = IsInch ? GraphicsUnit.Inch : GraphicsUnit.Millimeter;
                #region 根据模板打印
                ryCommon.Storage tStor_set = new ryCommon.Storage(mod_xml);
                tStor_set.SelectNode2("id", "set");
                double mmWidth = tStor_set.GetAttrValue("Width", 0d);
                double mmHeight = tStor_set.GetAttrValue("Height", 0d);
                if (IsInch)
                {
                    mmWidth = RySet.MMToInches(mmWidth);
                    mmHeight = RySet.MMToInches(mmHeight);
                }
                string picPath = RySet.GetTruePath(tStor_set.GetAttrValue("PreviewPicPath", ""));
                tStor_set.SelectNode2("id", "print_xml");
                ryCommon.Storage tStor = new ryCommon.Storage(tStor_set.GetAttrValue("Value"));
                System.Xml.XmlNodeList list = tStor.GetList();
                if (System.IO.File.Exists(picPath))
                {
                    Image image = Image.FromFile(picPath);
                    if (isPreview)
                    {
                        
                        Bitmap pic = (Bitmap)image;
                        //pic.SetResolution(dpiValue, dpiValue);
                        e.Graphics.DrawImage(pic, 0, 0, (float)mmWidth, (float)mmHeight);
                    }
                }
                for (int i = 0; i < list.Count; i++)
                {
                    tStor.SelectNode3(list[i]);
                    Font _Font = new Font(FontName, tStor.GetAttrValueByInt("FontSize", 10), FontStyle.Regular);
                    bool Multiline = tStor.GetAttrValueByBool("Multiline", false);
                    SizeF size = new SizeF((float)(tStor.GetAttrValue("Width", 100f)), (float)(tStor.GetAttrValue("Height", 21f)));
                    PointF location = new PointF((float)(tStor.GetAttrValue("Left", 0f) + MarginLeft), (float)(tStor.GetAttrValue("Top", 0f) + MarginTop));
                    if (IsInch)
                    {
                        size = new SizeF(RySet.MMToInches(size.Width), RySet.MMToInches(size.Height));
                        location = new PointF(RySet.MMToInches(location.X), RySet.MMToInches(location.Y));
                    }
                    string title = tStor.GetAttrValue("Title");
                    ClsProperty.En_Type _type = ClsProperty.En_Type.自定义;
                    try
                    {
                        _type = (ClsProperty.En_Type)tStor.GetAttrValueByInt("sType", 0);
                    }
                    catch { }
                    List<string> value_list = new List<string>();
                    #region 转换值
                    switch (_type)
                    {
                        case ClsProperty.En_Type.自定义:
                            string format = tStor.GetAttrValue("format");
                            if (format == "")
                            {
                                if (tStor.GetAttrValue("value") == "")
                                { value_list.Add(title); }
                                else
                                {
                                    value_list.Add(tStor.GetAttrValue("value"));
                                }
                            }
                            else
                            {
                                value_list.Add(DateTime.Now.ToString(format));
                            }
                            break;
                        case ClsProperty.En_Type.数据字段:
                            string datasource = tStor.GetAttrValue("DataSource");
                            if (datasource != "")
                            {
                                DataTable dt = new DataTable();
                                HashItem item = new HashItem();
                                if (!dt_list.ContainsKey(datasource))
                                {
                                    OnDataSet?.Invoke(datasource, out dt);
                                    item.dt = dt;
                                    dt_list.Add(datasource, item);
                                }
                                else
                                {
                                    item = (HashItem)dt_list[datasource];
                                    if (item.dt!= null)
                                        dt = item.dt;
                                }
                                if (!dt.Columns.Contains(tStor.GetAttrValue("value"))) { item.ReadEnd = true; continue; }
                                int PageCount = tStor.GetAttrValue("PageCount", 0);
                                int startRow = curPageIndex* PageCount;
                                int endRow = dt.Rows.Count;
                                if(PageCount>0)
                                {
                                    if((curPageIndex+1) * PageCount>= dt.Rows.Count)
                                    {
                                        endRow = dt.Rows.Count;
                                        item.ReadEnd = true;
                                    }
                                    else
                                    {
                                        endRow = (curPageIndex + 1) *PageCount;
                                    }
                                }
                                else
                                {
                                    item.ReadEnd = true;
                                }
                                dt_list[datasource] = item;
                                for (int m = startRow; m < endRow; m++)
                                {
                                    value_list.Add(dt.Rows[m][tStor.GetAttrValue("value")].ToString());
                                }
                            }
                            break;
                    }
                    #endregion
                    float total_top = location.Y;
                    #region 打印内容
                    for (int k = 0; k < value_list.Count; k++)
                    {
                        location.Y = total_top;
                        string value = value_list[k];
                        float rowHeight = e.Graphics.MeasureString(value + "有", _Font).Height;
                        if (value != "")
                        {
                            StringFormat sf = new StringFormat();
                            Brush fontBrush = Brushes.Black;
                            if (tStor.GetAttrValue("NoPrint", false))
                            {
                                if (isPreview)
                                {
                                    fontBrush = Brushes.Blue;
                                }
                                else
                                { continue; }
                            }
                            if (Multiline)
                            {
                                //sf.Alignment = StringAlignment.Center;
                                //sf.LineAlignment = StringAlignment.Center;
                                RectangleF rect = new RectangleF(location, size);
                                rowHeight = rect.Height;
                                e.Graphics.DrawString(value, _Font, fontBrush, rect, sf);
                            }
                            else
                            {
                                #region 单行打印
                                switch (tStor.GetAttrValue("align"))
                                {
                                    case "Left":
                                        sf.Alignment = StringAlignment.Near;
                                        break;
                                    case "Right":
                                        sf.Alignment = StringAlignment.Far;
                                        break;
                                    case "Center":
                                        sf.Alignment = StringAlignment.Center;
                                        break;
                                }
                                //sf.LineAlignment = sf.Alignment;
                                if (sf.Alignment == StringAlignment.Center)
                                {
                                    SizeF _size = e.Graphics.MeasureString(value, _Font);
                                    if (size.Width < _size.Width) { size.Width = _size.Width; }
                                    size.Height = _size.Height;
                                    RectangleF rect = new RectangleF(location, size);
                                    sf.LineAlignment = sf.Alignment;
                                    e.Graphics.DrawString(value, _Font, fontBrush, rect, sf);
                                }
                                else
                                {
                                    e.Graphics.DrawString(value, _Font, fontBrush, location, sf);
                                }
                                #endregion
                            }
                        }
                        if (IsInch)
                        { total_top += rowHeight + RySet.MMToInches(tStor.GetAttrValue("LineSpace", 0)); }
                        else
                        {
                            total_top += rowHeight + tStor.GetAttrValue("LineSpace", 0);
                        }
                    }
                    #endregion
                }
                #endregion
            }
            catch { }
            #region 判断记录是否已经打印完
            bool PageEnd = true;
            foreach (DictionaryEntry de in dt_list)
            {
                HashItem _item = (HashItem)de.Value;
                if (!_item.ReadEnd)
                {
                    PageEnd = false;
                    break;
                }
            }
            if (PageEnd) { e.HasMorePages = false; }///如果已经是尾页,则不继续打印
            else
            {
                if(MaxPage>0)
                {
                    if(curPageIndex>= MaxPage)
                    {
                        e.HasMorePages = false;
                        return;
                    }
                }
                e.HasMorePages = true;
                curPageIndex++;
            } 
            #endregion
        }
    }
    class HashItem
    {
        public DataTable dt=new DataTable();
        public bool ReadEnd = false;
    }
}
