using DotNetSAPI;
using RGD.Common;
using RGD.DataService;
using RGD.DBUtility;
using RGD.ZhiQianAPI;
using RGD.MdsAPI;
using RGD.MdsAPI.WMS;
using System;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Xml;

namespace RGD.WCS
{
    public partial class FrmMain : Form
    {
        #region 窗体显示

        [System.Runtime.InteropServices.DllImport("user32")]
        private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags);

        private const int AW_HOR_POSITIVE = 0x0001;//自左向右显示窗口，该标志可以在滚动动画和滑动动画中使用。使用AW_CENTER标志时忽略该标志
        private const int AW_HOR_NEGATIVE = 0x0002;//自右向左显示窗口，该标志可以在滚动动画和滑动动画中使用。使用AW_CENTER标志时忽略该标志
        private const int AW_VER_POSITIVE = 0x0004;//自顶向下显示窗口，该标志可以在滚动动画和滑动动画中使用。使用AW_CENTER标志时忽略该标志
        private const int AW_VER_NEGATIVE = 0x0008;//自下向上显示窗口，该标志可以在滚动动画和滑动动画中使用。使用AW_CENTER标志时忽略该标志该标志
        private const int AW_CENTER = 0x0010;//若使用了AW_HIDE标志，则使窗口向内重叠；否则向外扩展
        private const int AW_HIDE = 0x10000;//隐藏窗口
        private const int AW_ACTIVE = 0x20000;//激活窗口，在使用了AW_HIDE标志后不要使用这个标志
        private const int AW_SLIDE = 0x40000;//使用滑动类型动画效果，默认为滚动动画类型，当使用AW_CENTER标志时，这个标志就被忽略
        private const int AW_BLEND = 0x80000;//使用淡入淡出效果
        private static FrmMain _formInstance;

        #endregion 窗体显示

        private static Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private static byte[] result = new byte[1024];
        public static int taskId = 0;
        public static int taskCount = 0;
        public static FrmMain FormInstance
        {
            get
            {
                if (_formInstance == null)
                {
                    _formInstance = new FrmMain();
                }
                return _formInstance;
            }
            set { _formInstance = value; }
        }

        private SpeechVoiceSpeakFlags SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
        public SpVoice Voice = new SpVoice();

        public FrmMain()
        {
            InitializeComponent();
            _formInstance = this;
            //黑匣子文件 文件清理
            RGD.Common.CCarryConvert.NeatenDarkCasket();

            #region 系统配置文件初始化

            ////路径搜索方式
            //CStaticClass.RouteSearchMode = CommonClassLib.AppSettings.GetValue("RouteSearchMode");
            ////双叉关联任务允许等待的时间
            //CStaticClass.DoubleForkWaitTime = CommonClassLib.AppSettings.GetValue("DoubleForkWaitTime");
            ////AGV是否允许单叉动作
            //CStaticClass.AGVAllowSingleFork = CommonClassLib.AppSettings.GetValue("AGVAllowSingleFork");
            ////日志黑匣子保存时间
            //CStaticClass.SaveDays = CommonClassLib.AppSettings.GetValue("SaveDays");
            ////移动设备是否被提前触发将取
            //CStaticClass.MovedDeviceAheadTrigger = CommonClassLib.AppSettings.GetValue("MovedDeviceAheadTrigger");
            ////堆垛机出库是否检测目标输送机空闲和有物
            //CStaticClass.OutDetectArrowIdleGoods = CommonClassLib.AppSettings.GetValue("OutDetectArrowIdleGoods");
            ////设备发生故障自动变更路径
            //CStaticClass.DeviceErrorAutoModifyRoutePath = CommonClassLib.AppSettings.GetValue("DeviceErrorAutoModifyRoutePath");

            #endregion 系统配置文件初始化

            //初始化管理和调度交互状态
            IOControlService.AddIOControlStatus();
            ////初始化错误信息
            BaseDeviceService.AddDeviceErrors();

            //加载全局站台信息
            CConfig.LoadConfig();
            //初始化设备静态信息
            BaseDeviceService.AddDeviceInfo();
            //虚拟设备 PLC_DB2交互数据
            CStaticClass.devinfo28 = BaseDeviceService.GetDeviceInfo(65534);



            #region 界面布局
            //主控
            FrmControlMonitor.FormInstance.Show(this.dockPanel1);
            FrmControlMonitor.FormInstance.DockTo(this.dockPanel1, DockStyle.Fill);
            //任务列表窗口
            FrmTaskList Frmlist = new FrmTaskList();
            Frmlist.Show(this.dockPanel1);
            Frmlist.DockTo(this.dockPanel1, DockStyle.Bottom);
            Frmlist.DockState = WeifenLuo.WinFormsUI.Docking.DockState.DockBottom;
            Frmlist.AutoHidePortion = 0.28;//(double)Frmlist.Height / (double)this.dockPanel1.Height;
            Frmlist.CloseButton = false;
            //运行异常窗口
            FrmErrorMessage frmErrorMessage = new FrmErrorMessage();
            frmErrorMessage.Show(this.dockPanel1);
            frmErrorMessage.DockTo(this.dockPanel1, DockStyle.Bottom);
            frmErrorMessage.DockState = WeifenLuo.WinFormsUI.Docking.DockState.DockBottomAutoHide;
            frmErrorMessage.CloseButton = false;
            //帮助信息窗口
            FrmHelp frmHelp = new FrmHelp();
            frmHelp.Show(this.dockPanel1);
            frmHelp.DockTo(this.dockPanel1, DockStyle.Bottom);
            frmHelp.DockState = WeifenLuo.WinFormsUI.Docking.DockState.DockBottomAutoHide;
            frmHelp.CloseButton = false;

            #endregion 界面布局

            //检测是否登录
            if (FrmLogin.FormInstance.ShowDialog() != DialogResult.OK) return; //dzf 调试时注释掉
            CCarryConvert.WriteDarkCasket("Login", "UserID：" + CStaticClass.UserID + "的操作日志", "成功登录系统", "", "");
            this.DoubleBuffered = true;
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
            this.UpdateStyles();
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            //SocketService();
        }

        #region 命令开关 接口服务

        private CControl cc = new CControl();
        private CListenPLCAsk cplc = new CListenPLCAsk();

        /// <summary>
        /// 打开命令开关
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MITurnOn_Click(object sender, EventArgs e)
        {
            try
            {
                MMDarketManage.Enabled = true;
                MMUserManage.Enabled = true;
                MIUserInfoManage.Enabled = true;
                CStaticClass.Order = true;
                MITurnOff.Enabled = true;
                MITurnOn.Enabled = false;
                MITurnOff.Checked = false;
                MITurnOn.Checked = true;

                //执行自动命令
                CStaticClass.ReConnect();
                MMDarketManage.Checked = true;
                MMUserManage.Checked = false;
                MIUserInfoManage.Checked = false;
                this.Text = "瑞吉德自动化物流监控调度系统" + "--【正在执行自动命令！】";
                FrmControlMonitor.FormInstance.FlashPanit("tsStatus", "", false);
                //单次调用 与opc通信 取数据存放于CStaticClass.AllReturns
                LogUtil.WriteLog("", "打开命令开关-获取opc数据");
                CStaticClass.GetAllReturns();
                CConfig.StartAll();
                //后台独立线程 循环 解析plc读取的数据 CStaticClass.AllReturns 300ms 更新到设备内存中
                LogUtil.WriteLog("", "打开命令开关-启动opcAllReturns数据解析");
                CParsePLCData.StartListen();
                //AGV相关服务启动
                HttpServer.start();
                //终端socket启动
            }
            catch (Exception ex)
            {
                MessageBox.Show(":" + ex.Message, "操作提示：", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
            }
        }

        /// <summary>
        /// 关闭命令开关
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MITurnOff_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("您确认要“关闭命令开关”吗？如果“关闭命令开关”将导致调度计算机与所有设备通讯中断！", "操作提示：", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
            {
                return;
            }
            CStaticClass.Order = false;
            MITurnOff.Enabled = false;
            MITurnOn.Enabled = true;
            MITurnOn.Checked = false;
            MITurnOff.Checked = true;
            HttpServer.close();
            this.Text = "瑞吉德自动化物流监控调度系统";
            //getAllReturnTimer.Enabled = false;
            //getAllReturnTimer.Stop();
            CConfig.StopAll();
            CParsePLCData.EndListen();
        }

        #endregion 命令开关 接口服务

        #region 按钮事件

        /// <summary>
        /// 指令队列管理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MIAltMonitor_Click(object sender, EventArgs e)
        {
            FrmModifyMonitor.FormInstance.ShowDialog();
        }

        /// <summary>
        /// 调度任务管理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MIAltManange_Click(object sender, EventArgs e)
        {
            FrmModifyManage.FormInstance.ShowDialog();
        }

        /// <summary>
        /// 单一设备指令
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            FrmHandCommand.FormInstance.ShowDialog();
        }

        private void MIManageShow_Click(object sender, EventArgs e)
        {
            FrmAutoCommand.FormInstance.ShowDialog();
        }

        /// <summary>
        /// 叠盘机缓存管理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MIdp_Click(object sender, EventArgs e)
        {
            FrmStackerCache.FormInstance.ShowDialog();
        }

        /// <summary>
        /// 清除任务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MIClearTask_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("是否清除调度系统收到的任务信息？", "警告", MessageBoxButtons.YesNo);
            if (dr == DialogResult.Yes)
            {
                DbHelperSQL.ExecuteSql("update t_warehouse set f_task_no='',f_task_type='',f_task_status='FREE',f_equip_type='',F_IO_WH_SORT_CODE='',F_LASTBOX_REACH_FLAG=0");
                DbHelperSQL.ExecuteSql("delete t_manage_task");
                DbHelperSQL.ExecuteSql("delete t_monitor_task");
            }
        }

        /// <summary>
        /// 浏览黑匣子文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MISeeDarket_Click(object sender, EventArgs e)
        {
            FrmBrowseDarkCasket.FormInstance.ShowDialog();
        }

        private void MIAbout_Click(object sender, EventArgs e)
        {
            new FrmAboutBox().ShowDialog();
        }



        private void MMExitSystem_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("真的要退出系统？", "提示", MessageBoxButtons.YesNo);
            if (dr == DialogResult.Yes)
            {
                this.Close();
            }
        }

        private void DeviceStatusSearchMenuItem_Click(object sender, EventArgs e)
        {
            FrmDeviceErrorLog.FormInstance.ShowDialog();
        }

        /// <summary>
        /// 设备状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MIDeviceState_Click(object sender, EventArgs e)
        {
            FrmDeviceInfoEdit.FormInstance.ShowDialog();
        }

        #endregion 按钮事件

        private void MonitorDataBackUpMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string localFilePath;
                string saveFilepath = "E:\\";
                saveFileDialog1.Title = "备份调度系统数据库...";
                saveFileDialog1.FileName = DateTime.Now.ToString("yyyyMMddHHmmss") + "DBBak";
                saveFileDialog1.Filter = "所有文件(*.*)|*.*";

                if (System.IO.Directory.Exists(saveFilepath))//文件目录是否存在
                {
                    saveFileDialog1.InitialDirectory = saveFilepath;
                }

                saveFileDialog1.RestoreDirectory = true;
                //saveFileDialog1.CheckFileExists = true;
                saveFileDialog1.CheckPathExists = true;
                saveFileDialog1.OverwritePrompt = true;

                if (this.saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    localFilePath = saveFileDialog1.FileName.ToString();

                    string sql = string.Format("Backup database AHFY_WCS to disk = '{0}'", localFilePath); //MyTest为远程数据库名称，也可以改成用变量传入
                    DbHelperSQL.ExecuteSql(sql);

                    //下面判断文件是否生成来确定是否备份成功
                    if (System.IO.File.Exists(localFilePath))
                    {
                        MessageBox.Show("数据库备份成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                    }
                    else
                    {
                        MessageBox.Show("数据库备份失败!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }

                    //还原是一样的.只是sql改成"RESTORE FILELISTONLY  FROM DISK ='路径'"
                }
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.TopMost = true;
            this.Visible = true;
            this.TopMost = false;
            this.WindowState = FormWindowState.Maximized;
        }

        private void notifyIcon1_BalloonTipShown(object sender, EventArgs e)
        {
            try
            {
                //Voice.Speak("123", SpFlags);
                //Voice.Speak(notifyIcon1.BalloonTipText, SpFlags);
            }
            catch (Exception ex)
            {
            }
        }

        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("您确认要退出瑞吉德自动化物流监控调度系统吗？", "操作提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                CParsePLCData.EndListen();
                CCarryConvert.WriteDarkCasket("Login", "UserID：" + CStaticClass.UserID + "的操作日志", "退出系统", "", "");
                System.Diagnostics.Process.GetCurrentProcess().Kill();
            }
            else
            {
                e.Cancel = true;
            }
        }

        private void SocketService()
        {
            string IP = AppSettings.GetValue("AndroidIP");
            int port = int.Parse(AppSettings.GetValue("Port"));
            socket.Bind(new IPEndPoint(IPAddress.Parse(IP), port));
            socket.Listen(10);

            Thread myThread = new Thread(ListenClientConnect);

            myThread.Start();
        }

        /// <summary>
        /// 监听客户端连接
        /// </summary>
        private static void ListenClientConnect()
        {
            while (true)
            {
                Socket clientSocket = socket.Accept();
                //System.Console.WriteLine("客户的本地端口是：" + clientSocket.LocalEndPoint.ToString());
                //System.Console.WriteLine("客户端是：" + clientSocket.RemoteEndPoint.ToString());
                System.Console.WriteLine(clientSocket.Connected);
                Thread receiveThread = new Thread(ReceiveMessage);
                System.Console.WriteLine(clientSocket.Connected);
                receiveThread.Start(clientSocket);
            }
        }

        private static void ReceiveMessage(object clientSocket)
        {
            Socket myClientSocket = (Socket)clientSocket;
            //System.Console.WriteLine(myClientSocket.Connected+"1");
            while (true)
            {
                //System.Console.WriteLine(myClientSocket.Connected + "2");
                try
                {
                    //System.Console.WriteLine(myClientSocket.Connected + "3");
                    if (myClientSocket.Connected && myClientSocket != null)
                    {
                        //通过clientSocket接收数据
                        int receiveNumber = myClientSocket.Receive(result);
                        if (receiveNumber == 0)
                        {
                            return;
                        }
                        Console.WriteLine(myClientSocket.RemoteEndPoint.ToString(), Encoding.UTF8.GetString(result, 0, receiveNumber));
                        string receiveData = Encoding.UTF8.GetString(result, 0, receiveNumber);
                        XmlDocument xmlDoc = new XmlDocument();
                        xmlDoc.LoadXml(receiveData);

                        XmlNode nodeRoot = xmlDoc.SelectSingleNode("DataFromZD");
                        string method = nodeRoot.SelectSingleNode(@"Method").InnerText;
                        XmlNodeList xnlBOX_BARCODE = nodeRoot.SelectNodes(@"BoxsCodes");
                        string sBOX_BARCODE = string.Empty;
                        foreach (XmlNode nBOX_BARCODE in xnlBOX_BARCODE)
                        {
                            sBOX_BARCODE += nBOX_BARCODE.InnerText + ",";
                        }
                        string[] boxs = Regex.Split(sBOX_BARCODE, "(?<=\\G.{12})");
                        if (boxs.Length > 1)
                        {
                            Array.Resize(ref boxs, boxs.Length - 1);
                        }

                        sBOX_BARCODE = string.Empty;
                        foreach (string box in boxs)
                        {
                            sBOX_BARCODE += box + ",";
                        }
                        sBOX_BARCODE = sBOX_BARCODE.TrimEnd(',');
                        XmlNodeList xnlGOODS_BARCODE = nodeRoot.SelectNodes(@"GoodsCodes");
                        string sGOODS_BARCODE = string.Empty;

                        foreach (XmlNode nGOODS_BARCODE in xnlGOODS_BARCODE)
                        {
                            sGOODS_BARCODE += nGOODS_BARCODE.InnerText + ",";
                        }
                        string[] goods = Regex.Split(sGOODS_BARCODE, "(?<=\\G.{22})");
                        if (goods.Length > 1)
                        {
                            Array.Resize(ref goods, goods.Length - 1);
                        }

                        sGOODS_BARCODE = string.Empty;
                        foreach (string good in goods)
                        {
                            sGOODS_BARCODE += good + ",";
                        }
                        sGOODS_BARCODE = sGOODS_BARCODE.TrimEnd(',');
                        DataView dvt = DbHelperSQL.Query("select F_TASK_NO,F_TASK_TYPE,F_EQUIP_TYPE from T_WareHouse").Tables[0].DefaultView;
                        string sResult = string.Empty;
                        bool bResult;
                        switch (method)
                        {
                            case "boxsin":
                                bResult = (new getInStackLocation()).Notify(dvt[0]["F_TASK_NO"].ToString(), sBOX_BARCODE, "", out sResult);
                                getInStackLocation.DATA outData = (new Base()).DeSerialize<getInStackLocation.DATA>(sResult);

                                if (bResult)
                                {
                                    new ManageTaskService().CreateMove(dvt[0]["F_TASK_NO"].ToString(), "1", "12001", outData.LOC_NO, sBOX_BARCODE, out sResult);
                                    sResult = outData.LOC_NO;
                                }
                                else
                                {
                                    sResult = outData.ERROR_INFO;
                                }
                                break;

                            case "goodsin":
                                bResult = (new getInOutCheckInfo()).Notify(dvt[0]["F_TASK_NO"].ToString(), "02", "", sBOX_BARCODE, sGOODS_BARCODE, out sResult);
                                getInOutCheckInfo.DATA op = (new Base()).DeSerialize<getInOutCheckInfo.DATA>(sResult);
                                if (bResult)
                                {
                                    sResult = "true";
                                }
                                else
                                {
                                    sResult = op.ERROR_INFO;
                                }
                                break;

                            case "outdetail":
                                bResult = (new getInOutCheckInfo()).Notify(dvt[0]["F_TASK_NO"].ToString(), "01", string.Empty, sBOX_BARCODE, string.Empty, out sResult);
                                if (bResult)
                                {
                                    getInOutCheckInfo.DATA info = (new Base()).DeSerialize<getInOutCheckInfo.DATA>(sResult);
                                    if (info.OUT_MODE.Equals("1"))
                                    {
                                        sResult = "true";
                                    }
                                    else if (info.OUT_MODE.Equals("2"))
                                    {
                                        sResult = "back";
                                    }
                                    else if (info.OUT_MODE.Equals("3"))
                                    {
                                        sResult = info.REPICK_ARRAY;
                                    }
                                }
                                else
                                {
                                    sResult = "false";
                                }
                                break;

                            case "gettask":
                                DataView dv = DbHelperSQL.Query("select * from t_warehouse").Tables[0].DefaultView;
                                sResult = dv[0]["f_task_no"].ToString();
                                break;

                            case "login":
                                Object o = DbHelperSQL.GetSingle("select * from t_base_users where f_password='" + sBOX_BARCODE + "'");
                                if (o != null)
                                {
                                    sResult = "true";
                                }
                                else
                                {
                                    sResult = "false";
                                }
                                break;
                        }

                        byte[] bs = Encoding.UTF8.GetBytes(sResult);
                        myClientSocket.Send(bs, bs.Length, 0);
                        myClientSocket.Close();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    myClientSocket.Shutdown(SocketShutdown.Both);
                    myClientSocket.Close();
                    break;
                }
            }
        }

        private void 海柔测试ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TEST1.FormInstance.ShowDialog();
        }

        private void 接口恢复ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmInterfaceRestart.FormInstance.ShowDialog();
        }

        private void FrmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            System.Diagnostics.Process.GetCurrentProcess().Kill();
        }

        private void MIHandShow_Click(object sender, EventArgs e)
        {
            FrmHandCommand.FormInstance.ShowDialog();
        }
    }
}