using System;
using System.Collections.Generic;
using System.Windows.Forms;
using ChuPiao.AutoPrint.Common;
using ChuPiao.AutoPrint.Desktop.Machine;
using ChuPiao.AutoPrint.Desktop.StatusBar;
using ChuPiao.AutoPrint.Desktop.Workbench;
using ChuPiao.AutoPrint.Services;
using ChuPiao.AutoPrint.Services.AutoPrint;
using ChuPiao.Common.Models;
using ChuPiao.Common.Utils;
using ChuPiao.AutoPrint.Services.OpenCode;

namespace ChuPiao.AutoPrint.Desktop
{
    public static class WorkbenchSingleton
    {
        static DefaultWorkbench workbench = null;
        static STAThreadCaller caller;
        public static Form MainForm
        {
            get
            {
                return (Form)workbench;
            }
        }

        public static void InitializeWorkbench()
        {
            LogUtil.Setup();
            LogUtil.LogInfo("程序开始启动……");

            //从本地配置中读取出票速度，默认200毫秒
            string str = LocalConfigUtil.GetConfig("KeyInterval");
            int keyInterval = 200;
            if (!string.IsNullOrEmpty(str))
            {
                Int32.TryParse(str, out keyInterval);
            }
            LocalConfigUtil.KeyInterval = keyInterval;

            str = LocalConfigUtil.GetConfig("TicketInterval");
            int ticketInterval = 1500;
            if (!string.IsNullOrEmpty(str))
            {
                Int32.TryParse(str, out ticketInterval);
            }
            LocalConfigUtil.TicketInterval = ticketInterval;

            //从配置文件读取彩票机设置
            LotMachineService.InitializeLotMachine();

            

            StatusBarService.Initialize();

            workbench = new DefaultWorkbench(); 
            MessageService.MainForm = workbench;
            caller = new STAThreadCaller(workbench);
            workbench.InitializeWorkspace();

            ChuPiao.Common.Communication.GtdJson.PackSetting.Instance.Configure();

            Form f = (Form)workbench;
            f.Show();
            f.Focus();

            LotMachineService.StartDriver();
            LoggingService.Info("彩票机启动完成");

            //ExpectTaskService.initExpect();

            Application.Run(f);

            BeepUtil.Instance().Dispose();
        }

        #region Safe Thread Caller
        /// <summary>
        /// Description of STAThreadCaller.
        /// </summary>
        private class STAThreadCaller
        {
            Control ctl;

            public STAThreadCaller(Control ctl)
            {
                this.ctl = ctl;
            }

            public object Call(Delegate method, object[] arguments)
            {
                if (method == null)
                {
                    throw new ArgumentNullException("method");
                }
                return ctl.Invoke(method, arguments);
            }

            public void BeginCall(Delegate method, object[] arguments)
            {
                if (method == null)
                {
                    throw new ArgumentNullException("method");
                }
                ctl.BeginInvoke(method, arguments);
            }
        }

        public static bool InvokeRequired
        {
            get
            {
                if (workbench == null)
                    return false; // unit test mode, don't crash
                else
                    return ((Form)workbench).InvokeRequired;
            }
        }

        /// <summary>
        /// Throws an exception if the current thread is not the main thread.
        /// </summary>
        internal static void AssertMainThread()
        {
            if (InvokeRequired)
            {
                throw new InvalidOperationException("This operation can be called on the main thread only.");
            }
        }

        /// <summary>
        /// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
        /// operation, which can result in a dead-lock when the main thread waits for a lock
        /// held by this thread!
        /// </summary>
        public static R SafeThreadFunction<R>(Func<R> method)
        {
            return (R)caller.Call(method, new object[0]);
        }

        /// <summary>
        /// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
        /// operation, which can result in a dead-lock when the main thread waits for a lock
        /// held by this thread!
        /// </summary>
        public static R SafeThreadFunction<A, R>(Func<A, R> method, A arg1)
        {
            return (R)caller.Call(method, new object[] { arg1 });
        }

        /// <summary>
        /// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
        /// operation, which can result in a dead-lock when the main thread waits for a lock
        /// held by this thread!
        /// </summary>
        public static void SafeThreadCall(Action method)
        {
            caller.Call(method, new object[0]);
        }

        /// <summary>
        /// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
        /// operation, which can result in a dead-lock when the main thread waits for a lock
        /// held by this thread!
        /// </summary>
        public static void SafeThreadCall<A>(Action<A> method, A arg1)
        {
            caller.Call(method, new object[] { arg1 });
        }

        /// <summary>
        /// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
        /// operation, which can result in a dead-lock when the main thread waits for a lock
        /// held by this thread!
        /// </summary>
        public static void SafeThreadCall<A, B>(Action<A, B> method, A arg1, B arg2)
        {
            caller.Call(method, new object[] { arg1, arg2 });
        }

        /// <summary>
        /// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
        /// operation, which can result in a dead-lock when the main thread waits for a lock
        /// held by this thread!
        /// </summary>
        public static void SafeThreadCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3)
        {
            caller.Call(method, new object[] { arg1, arg2, arg3 });
        }
        public static void SafeThreadCall<A, B, C,D>(Action<A, B, C,D> method, A arg1, B arg2, C arg3, D arg4)
        {
            caller.Call(method, new object[] { arg1, arg2, arg3,arg4 });
        }

        /// <summary>
        /// Makes a call GUI threadsafe without waiting for the returned value.
        /// </summary>
        public static void SafeThreadAsyncCall(Action method)
        {
            caller.BeginCall(method, new object[0]);
        }

        /// <summary>
        /// Makes a call GUI threadsafe without waiting for the returned value.
        /// </summary>
        public static void SafeThreadAsyncCall<A>(Action<A> method, A arg1)
        {
            caller.BeginCall(method, new object[] { arg1 });
        }

        /// <summary>
        /// Makes a call GUI threadsafe without waiting for the returned value.
        /// </summary>
        public static void SafeThreadAsyncCall<A, B>(Action<A, B> method, A arg1, B arg2)
        {
            caller.BeginCall(method, new object[] { arg1, arg2 });
        }

        /// <summary>
        /// Makes a call GUI threadsafe without waiting for the returned value.
        /// </summary>
        public static void SafeThreadAsyncCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3)
        {
            caller.BeginCall(method, new object[] { arg1, arg2, arg3 });
        }
        #endregion
    }
}
