using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using DevExpress.DataAccess.Json;
using DevExpress.DataAccess.Native.Json;
using DevExpress.DataAccess.ObjectBinding;
using DevExpress.XtraPrinting.Preview;
using DevExpress.XtraReports.Localization;
using DevExpress.XtraReports.UI;
using Newtonsoft.Json;
using RibbonReportDesigner;

namespace GetEasy.Node.Printer
{
    public class NodeReportDesigner
    {
        private static ManualResetEvent _nodeThread;
        private static ManualResetEvent _formThread;
        private static SaveObj _saveObj;

        ///// <summary>
        /////  保存回调方法,防止被GC
        ///// </summary>
        //private static Dictionary<Guid, SaveResultCallback> dicResult = new Dictionary<Guid, SaveResultCallback>();
        static NodeReportDesigner()
        {
            //AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }
        //private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        //{
        //    MessageBox.Show(args.Name + "加载失败");
        //    return null;
        //}
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
        public delegate void SaveCallback([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String template, SaveResultCallback resultCallback);
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
        public delegate void SaveResultCallback(bool isSuccess);



        [DllExport(CallingConvention = CallingConvention.Winapi, ExportName = "designerReport")]
        public static void DesignerReport([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String template,
            [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String templateData)
        {
            _nodeThread = new ManualResetEvent(true);
            _formThread = new ManualResetEvent(true);
            _saveObj = new SaveObj();


            var thread = new Thread(() =>
            {
                Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");
                Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");
                // 加载  Newtonsoft.Json;
                JsonConvert.DeserializeObject("{}");
                XtraReport report = new XtraReport();
                try
                {
                    var form = new OfficeInspiredMainForm();
                    if (!String.IsNullOrEmpty(template))
                    {
                        byte[] array = Encoding.UTF8.GetBytes(template);
                        MemoryStream stream = new MemoryStream(array);
                        report.LoadLayoutFromXml(stream);
                    }

                    if (!String.IsNullOrEmpty(templateData))
                    {
                        JsonDataSource dataSource = null;
                        if (report.DataSource != null && report.DataSource is JsonDataSource)
                        {
                            dataSource = report.DataSource as JsonDataSource;
                        }
                        else
                        {
                            dataSource = new JsonDataSource();
                        }
                        var jsonDataSource = new CustomJsonSource(templateData);
                        dataSource.JsonSource = jsonDataSource;
                        report.DataSource = dataSource;
                    }

                    form.OnSave += (designPanel) =>
                    {
                        MemoryStream stream = new MemoryStream();
                        designPanel.Report.SaveLayoutToXml(stream);
                        _saveObj.SaveData = Encoding.UTF8.GetString(stream.ToArray());

                        _formThread.Reset(); // 切换回主线程保存数据
                        _nodeThread.Set();
                        _formThread.WaitOne();

                        if (!_saveObj.IsSaveSuccess)
                        {
                            MessageBox.Show("保存失败!", "提示");
                        }
                        else
                        {
                            designPanel.ReportState = DevExpress.XtraReports.UserDesigner.ReportState.Saved;
                        }


                    };

                    form.OpenReport(report);
                    form.ShowDialog();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                _saveObj.SaveData = null; // 清空保存数据并且启动主线程
                _nodeThread.Set();
            });
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        [DllExport(CallingConvention = CallingConvention.Winapi, ExportName = "waitSaveOrClose")]
        public static void WaitSaveOrClose(SaveCallback saveCallback)
        {
            //RibbonControllerBase data;
            _nodeThread.Reset();
            _nodeThread.WaitOne();

            saveCallback(_saveObj.SaveData, (result) =>
            {
                _saveObj.IsSaveSuccess = result;
                _formThread.Set(); // 重新等待设计窗口信息
            });
        }

        [DllExport(CallingConvention = CallingConvention.Winapi, ExportName = "reportShowPreview")]
        public static void ReportShowPreview([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String fileName, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String jsonData)
        {
            // 加载  Newtonsoft.Json;
            JsonConvert.DeserializeObject("{}");

            var thread = new Thread(() =>
            {
                Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");
                Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");
                XtraReport report = XtraReport.FromFile(fileName);

                JsonDataSource dataSource = null;
                if (report.DataSource != null && report.DataSource is JsonDataSource)
                {
                    dataSource = report.DataSource as JsonDataSource;
                }
                else
                {
                    dataSource = new JsonDataSource();
                }
                var jsonDataSource = new CustomJsonSource(jsonData);
                dataSource.JsonSource = jsonDataSource;
                report.DataSource = dataSource;
                report.ShowPreviewDialog();
            });
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }


        [DllExport(CallingConvention = CallingConvention.Winapi, ExportName = "reportPrinter")]
        public static void ReportPrinter([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String fileName, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String jsonData, bool isSelectPrinter)
        {
            var thread = new Thread(() =>
            {
                try
                {
                    //Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");
                    //Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");
                    var report = XtraReport.FromFile(fileName);

                    JsonDataSource dataSource = null;
                    if (report.DataSource != null && report.DataSource is JsonDataSource)
                    {
                        dataSource = report.DataSource as JsonDataSource;
                    }
                    else
                    {
                        dataSource = new JsonDataSource();
                    }
                    var jsonDataSource = new CustomJsonSource(jsonData);
                    dataSource.JsonSource = jsonDataSource;
                    report.DataSource = dataSource;
                    if (isSelectPrinter)
                    {
                        report.PrintDialog();
                    }
                    else
                    {
                        report.Print();
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.InnerException.Message + '\n' + e.InnerException.StackTrace);
                }
            });
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }


        [DllExport(CallingConvention = CallingConvention.Winapi, ExportName = "reportToImage")]
        public static String ReportToImage([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String fileName, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]String jsonData)
        {
            try
            {
                //Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");
                //Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");
                var report = XtraReport.FromFile(fileName);

                JsonDataSource dataSource = null;
                if (report.DataSource != null && report.DataSource is JsonDataSource)
                {
                    dataSource = report.DataSource as JsonDataSource;
                }
                else
                {
                    dataSource = new JsonDataSource();
                }
                var jsonDataSource = new CustomJsonSource(jsonData);
                dataSource.JsonSource = jsonDataSource;
                report.DataSource = dataSource;
                MemoryStream stream = new MemoryStream();
                report.ExportToImage(stream, ImageFormat.Jpeg);
                return Convert.ToBase64String(stream.GetBuffer());
            }
            catch (Exception e)
            {
                MessageBox.Show(e.InnerException.Message + '\n' + e.InnerException.StackTrace);
                return null;
            }
        }



        public class SaveObj
        {
            public String SaveData;
            public bool IsSaveSuccess;
        }
    }
}