using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Drawing;
using System.Collections;
using irisHelper;
using irisDataBase;
using IrisDoor;
using irisRefactor.FrmService;

namespace irisRefactor.IrisScoket
{
    class SocketHelper
    {
        public static Socket serverSocket;
        private static Socket clientSocket;
        private List<Socket> allClientSocket = new List<Socket>();
        private List<string> allClientIp = new List<string>();//存储客户端IP
        private static string dataFromOffline = "";
        private static string dataFromServer = "";
        private bool isWait = false;
        private static int resultRealTime = 99;//实时发送给后台的更新结果，99-还没更新或更新中，0-更新成功，-1-更新失败
        
        public void start()
        {
            IPAddress ip = IPAddress.Parse(IPAddress.Any.ToString());//set ip
            int port = Convert.ToInt32(ProMemory.appConfig.DbServerConfig.ListenPort);
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//initialize
            serverSocket.Bind(new IPEndPoint(ip, port));//bind
            serverSocket.Listen(10);

            //开启一个线程来监听客户端连接
            Thread myThread = new Thread(ListenClientConnect);
            myThread.IsBackground = true;
            myThread.Start();

            //进入监听状态
            LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "开始监听..." + port);
        }

        private void ListenClientConnect()
        {
            while (true)
            {                
                //Client连接上后 得到这个连接
                clientSocket = serverSocket.Accept();
                IPAddress remote_ip = ((IPEndPoint)clientSocket.RemoteEndPoint).Address;
                int portal = ((IPEndPoint)clientSocket.RemoteEndPoint).Port;
                allClientSocket.Add(clientSocket);
                allClientIp.Add(remote_ip.ToString() + ":" + portal.ToString());

                //开个线程接收Client信息
                Thread receivedThread = new Thread(ReceiveMessage);
                receivedThread.Start(clientSocket);
            }
        }

        private string GetHostIPv4()
        {
            String ip = "";

            IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());

            if (hostEntry.AddressList.Length > 0)
            {
                foreach (IPAddress ipAddr in hostEntry.AddressList)
                {
                    if (ipAddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        ip= ipAddr.ToString();
                    }

                }
            }

            return ip;
        }

        private void writeIpConfig()
        {
            String ip = GetHostIPv4();

            ConfigHelper.UpdateAppConfig("hostIp", ip);

            ProMemory.hostIp = ConfigHelper.GetAppConfig("hostIp");
        }

        private void ReceiveMessage(object clientSocket)
        {
            Socket myClientSocket = (Socket)clientSocket;

            int length = 0;

            byte[] buffer = new byte[1024];
            MemoryStream ms = new MemoryStream();

            writeIpConfig();

            try
            {
                if (isWait == true) return; 
                while ((length = myClientSocket.Receive(buffer)) > 0)
                {
                    ms.Write(buffer, 0, length);
                }
                ms.Flush();
                byte[] result = ms.ToArray();
                string msg = Encoding.UTF8.GetString(result, 0, result.Length);

                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "接收到更新信息");
                Byte[] sendMsg = Encoding.ASCII.GetBytes("ok");
                myClientSocket.Send(sendMsg);

                //msgStack.Push(msg);

                while (ProMemory.jobRuning)
                {
                    isWait = true;
                }
                if (ProMemory.isSyning) return;
                ProMemory.isSyning = true;
                ProMemory.IoControllService.setYellowFlash(false);
                Thread.Sleep(500);

                dealScoketMsg(myClientSocket, msg);
            }
            catch (Exception ex)
            {
                myClientSocket.Shutdown(SocketShutdown.Both);
                myClientSocket.Close();
            }

            myClientSocket.Close();
        }

        public void dealScoketMsg(Socket myClientSocket,String msg)
        {
            
            if (msg == "open")
            {
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "接收到后台的开门指令open...");
                //启用门禁功能
                if (ConfigHelper.GetAppConfig("doorSystemEnable") == "true")
                {
                    DoorSystem.open();
                }
                isWait = false;
                ProMemory.isSyning = false;
                ProMemory.cameraController.ContinuousShot_TriggerOff();
            }
            else if (msg.Contains("clear from offline"))
            {
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "接收到离线采集端清空命令...");
                int re = -1;
                try
                {
                    re = DatabaseLocal.OpenDB(ProMemory.appConfig.DbLocalConfig);
                    if (re == 0)
                    {
                        re = ProMemory.irisSynchDataService.clearTableFromOffline();//清空数据库
                    }

                    ProMemory.proConfig.CodeListMgr.CreateList(ProMemory.irisDataService.getAllIrisCodeLocal());//加载匹配列表

                    DatabaseLocal.CloseDB();
                }
                catch (Exception e)
                {
                    re = -1;
                    LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "数据库清空失败" + e.Message);
                }
                finally
                {
                        isWait = false;
                        ProMemory.isSyning = false;
                        ProMemory.cameraController.ContinuousShot_TriggerOff();
                }
            }
            else if (msg.Contains("data from offline"))
            {
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "接收到离线采集端的数据...");

                dataFromOffline = msg.Replace("data from offline", "");

                if (ProMemory.formType == "1")
                {
                    Form1.GetInstance().panel1.Visible = true;
                    Form1.GetInstance().label6.ForeColor = Color.LimeGreen;
                    Form1.GetInstance().label6.Text = "更新数据库中，请稍候...";
                    Form1.GetInstance().ReInitializeToSleep();
                }
                else if (ProMemory.formType == "2")
                {
                    Form2.GetInstance().panel1.Visible = true;
                    Form2.GetInstance().label6.ForeColor = Color.LimeGreen;
                    Form2.GetInstance().label6.Text = "更新数据库中，请稍候...";
                    Form2.GetInstance().panel1.Refresh();
                    Form2.GetInstance().ReInitializeToSleep();
                }

                //开启线程，同步数据库
                Thread updateThread = new Thread(updateDatabaseFromOffline);
                updateThread.Name = "syncScoketFromOffline";
                updateThread.IsBackground = true;
                updateThread.Start();
            }
            else if (msg == "update")
            {
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "接收到后台的数据库更新指令update...");

                if (ProMemory.formType == "1")
                {
                    Form1.GetInstance().panel1.Visible = true;
                    Form1.GetInstance().label6.ForeColor = Color.LimeGreen;
                    Form1.GetInstance().label6.Text = "正在更新数据库，请稍候...";
                    Form1.GetInstance().ReInitializeToSleep();
                }
                else if (ProMemory.formType == "2")
                {
                    Form2.GetInstance().panel1.Visible = true;
                    Form2.GetInstance().label6.ForeColor = Color.LimeGreen;
                    Form2.GetInstance().label6.Text = "正在更新数据库，请稍候...";
                    Form2.GetInstance().panel1.Refresh();
                    Form2.GetInstance().ReInitializeToSleep();
                }

                //开启线程，同步数据库
                Thread updateThread = new Thread(updateDatabase);
                updateThread.Name = "syncScoket";
                updateThread.IsBackground = true;
                updateThread.Start();
            }
            else if (msg.Contains("addPerson:") || msg.Contains("addPermission:") ||
                msg.Contains("deletePermission:") || msg.Contains("deletePerson:"))
            {
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "接收到后台的更新授权数据...");
                
                dataFromServer = msg;

                if (ProMemory.formType == "1")
                {
                    Form1.GetInstance().panel1.Visible = true;
                    Form1.GetInstance().label6.ForeColor = Color.LimeGreen;
                    Form1.GetInstance().label6.Text = "更新数据库中，请稍候...";
                    Form1.GetInstance().ReInitializeToSleep();
                }
                else if (ProMemory.formType == "2")
                {
                    Form2.GetInstance().panel1.Visible = true;
                    Form2.GetInstance().label6.ForeColor = Color.LimeGreen;
                    Form2.GetInstance().label6.Text = "更新数据库中，请稍候...";
                    Form2.GetInstance().ReInitializeToSleep();
                }

                resultRealTime = 99;

                //开启线程，同步数据库
                Thread updateThread = new Thread(updateDatabaseFromServer);
                updateThread.Name = "syncScoketFromServer";
                updateThread.IsBackground = true;
                updateThread.Start();

                while (true)
                {
                    if (resultRealTime == 0)
                    {
                        myClientSocket.Send(Encoding.ASCII.GetBytes("ok"));
                        ProMemory.isSyning = false;
                        if (ProMemory.isWait)
                            ProMemory.cameraController.ContinuousShot_TriggerOn();
                        else
                            ProMemory.cameraController.ContinuousShot_TriggerOff();
                        return;
                    }
                    else if (resultRealTime == -1)
                    {
                        myClientSocket.Send(Encoding.ASCII.GetBytes("fail"));
                        ProMemory.isSyning = false;
                        if (ProMemory.isWait)
                            ProMemory.cameraController.ContinuousShot_TriggerOn();
                        else
                            ProMemory.cameraController.ContinuousShot_TriggerOff();
                        return;
                    }
                }

            }
        }

        //从服务器同步数据库
        public void updateDatabase()
        {
            int re = -1;
            string resultString = "";
            try
            {
                re = DatabaseServer.OpenDB(ProMemory.appConfig.DbServerConfig);
                if (re == 0)
                {
                    re = DatabaseLocal.OpenDB(ProMemory.appConfig.DbLocalConfig);
                    if (re == 0)
                    {
                        re = ProMemory.irisSynchDataService.updateTable(ref resultString);
                    }
                }

                ProMemory.proConfig.CodeListMgr.CreateList(ProMemory.irisDataService.getAllIrisCodeLocal());//加载匹配列表

                DatabaseServer.CloseDB();
                DatabaseLocal.CloseDB();
            }
            catch (Exception e)
            {
                re = -1;
                resultString = "fail";
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "updateDatabase 数据库同步失败" + e.Message);
            }
            finally
            {
                try
                {
                    string serverIp = ProMemory.appConfig.DbServerConfig.ServerIp;
                    string serverAppPort = ProMemory.appConfig.DbServerConfig.ServerAppPort;

                    Http("http://" + serverIp + ":" + serverAppPort + "/device/receiveMsg?msg=" + resultString, null, null);

                    LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "回调信息：" + "http://" +
                        serverIp + ":" + serverAppPort + "/device/receiveMsg?msg=" + resultString);
                }
                catch (Exception e)
                {
                    LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "通知服务器数据库同步结果失败：" + e.Message);
                }
                finally
                {
                    if (re == 0)
                    {
                        if (ProMemory.formType == "1")
                        {
                            Form1.GetInstance().panel1.Visible = true;
                            Form1.GetInstance().label6.ForeColor = Color.LimeGreen;
                            Form1.GetInstance().label6.Text = "数据库更新成功！";
                        }
                        else if (ProMemory.formType == "2")
                        {
                            //Form2.GetInstance().panel1.Visible = true;
                            //Form2.GetInstance().label6.ForeColor = Color.LimeGreen;
                            //Form2.GetInstance().label6.Text = "数据库更新成功！";
                        }

                        LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "数据库同步成功");

                        new Thread(new ThreadStart(() =>
                        {
                            Thread.Sleep(3000);
                            if (ProMemory.formType == "1")
                                Form1.GetInstance().panel1.Visible = false;
                            else if (ProMemory.formType == "2")
                                Form2.GetInstance().panel1.Visible = false;

                            ProMemory.isSyning = false;
                            if (ProMemory.isWait)
                                ProMemory.cameraController.ContinuousShot_TriggerOn();
                            else
                                ProMemory.cameraController.ContinuousShot_TriggerOff();

                        })).Start();
                    }
                    else
                    {
                        if (ProMemory.formType == "1")
                        {
                            Form1.GetInstance().panel1.Visible = true;
                            Form1.GetInstance().label6.ForeColor = Color.OrangeRed;
                            Form1.GetInstance().label6.Text = "数据库更新失败！";
                        }
                        else if (ProMemory.formType == "2")
                        {
                            //Form2.GetInstance().panel1.Visible = true;
                            //Form2.GetInstance().label6.ForeColor = Color.OrangeRed;
                            //Form2.GetInstance().label6.Text = "数据库更新失败！";
                        }
                        new Thread(new ThreadStart(() =>
                        {
                            Thread.Sleep(3000);
                            if (ProMemory.formType == "1")
                                Form1.GetInstance().panel1.Visible = false;
                            else if (ProMemory.formType == "2")
                                Form2.GetInstance().panel1.Visible = false;

                            ProMemory.isSyning = false;
                            if (ProMemory.isWait)
                                ProMemory.cameraController.ContinuousShot_TriggerOn();
                            else
                                ProMemory.cameraController.ContinuousShot_TriggerOff();

                        })).Start();
                        LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "数据库同步失败");
                    }
                    isWait = false;
                }
            }
        }

        // 接收到离线采集端的数据，存入数据库
        public void updateDatabaseFromOffline()
        {
            int re = -1;
            try
            {
                re = DatabaseLocal.OpenDB(ProMemory.appConfig.DbLocalConfig);
                if (re == 0)
                {
                    re = ProMemory.irisSynchDataService.updateTableFromOffline(dataFromOffline);
                    dataFromOffline = "";
                }

                ProMemory.proConfig.CodeListMgr.CreateList(ProMemory.irisDataService.getAllIrisCodeLocal());//加载匹配列表

                DatabaseLocal.CloseDB();
            }
            catch (Exception e)
            {
                re = -1;
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "updateDatabase 数据库同步失败" + e.Message);
            }
            finally
            {
                    if (re == 0)
                    {
                        if (ProMemory.formType == "1")
                        {
                            Form1.GetInstance().panel1.Visible = true;
                            Form1.GetInstance().label6.ForeColor = Color.LimeGreen;
                            Form1.GetInstance().label6.Text = "数据库更新成功！";
                        }
                        else if (ProMemory.formType == "2")
                        {
                            //Form2.GetInstance().panel1.Visible = true;
                            //Form2.GetInstance().label6.ForeColor = Color.LimeGreen;
                            //Form2.GetInstance().label6.Text = "数据库更新成功！";
                        }

                        LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "数据库更新成功");

                        new Thread(new ThreadStart(() =>
                        {
                            Thread.Sleep(3000);
                            if (ProMemory.formType == "1")
                                Form1.GetInstance().panel1.Visible = false;
                            else if (ProMemory.formType == "2")
                                Form2.GetInstance().panel1.Visible = false;

                            ProMemory.isSyning = false;
                            if (ProMemory.isWait)
                                ProMemory.cameraController.ContinuousShot_TriggerOn();
                            else
                                ProMemory.cameraController.ContinuousShot_TriggerOff();

                        })).Start();
                    }
                    else
                    {
                        if (ProMemory.formType == "1")
                        {
                            Form1.GetInstance().panel1.Visible = true;
                            Form1.GetInstance().label6.ForeColor = Color.OrangeRed;
                            Form1.GetInstance().label6.Text = "数据库更新失败！";
                        }
                        else if (ProMemory.formType == "2")
                        {
                            //Form2.GetInstance().panel1.Visible = true;
                            //Form2.GetInstance().label6.ForeColor = Color.OrangeRed;
                            //Form2.GetInstance().label6.Text = "数据库更新失败！";
                        }
                        new Thread(new ThreadStart(() =>
                        {
                            Thread.Sleep(3000);
                            if (ProMemory.formType == "1")
                                Form1.GetInstance().panel1.Visible = false;
                            else if (ProMemory.formType == "2")
                                Form2.GetInstance().panel1.Visible = false;

                            ProMemory.isSyning = false;
                            if (ProMemory.isWait)
                                ProMemory.cameraController.ContinuousShot_TriggerOn();
                            else
                                ProMemory.cameraController.ContinuousShot_TriggerOff();

                        })).Start();

                        isWait = false;
                        LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "数据库更新失败");
                    }
            }
        }

        //接收到后台的更新数据
        public void updateDatabaseFromServer()
        {
            int re = -1;
            try
            {
                re = DatabaseLocal.OpenDB(ProMemory.appConfig.DbLocalConfig);
                if (re == 0)
                {
                    re = ProMemory.irisSynchDataService.updateTableFromServer(dataFromServer);
                    dataFromServer = "";
                }

                ProMemory.proConfig.CodeListMgr.CreateList(ProMemory.irisDataService.getAllIrisCodeLocal());//加载匹配列表

                DatabaseLocal.CloseDB();
            }
            catch (Exception e)
            {
                re = -1;
                LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "updateDatabase 数据库同步失败" + e.Message);
            }
            finally
            {
                if (re == 0)
                {
                    if (ProMemory.formType == "1")
                    {
                        Form1.GetInstance().panel1.Visible = true;
                        Form1.GetInstance().label6.ForeColor = Color.LimeGreen;
                        Form1.GetInstance().label6.Text = "数据库更新成功！";
                    }
                    else if (ProMemory.formType == "2")
                    {
                        //Form2.GetInstance().panel1.Visible = true;
                        //Form2.GetInstance().label6.ForeColor = Color.LimeGreen;
                        //Form2.GetInstance().label6.Text = "数据库更新成功！";
                    }

                    LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "数据库更新成功");

                    new Thread(new ThreadStart(() =>
                    {
                        Thread.Sleep(3000);
                        if (ProMemory.formType == "1")
                            Form1.GetInstance().panel1.Visible = false;
                        else if (ProMemory.formType == "2")
                            Form2.GetInstance().panel1.Visible = false;

                    })).Start();
                }
                else
                {
                    if (ProMemory.formType == "1")
                    {
                        Form1.GetInstance().panel1.Visible = true;
                        Form1.GetInstance().label6.ForeColor = Color.OrangeRed;
                        Form1.GetInstance().label6.Text = "数据库更新失败！";
                    }
                    else if (ProMemory.formType == "2")
                    {
                        // Form2.GetInstance().panel1.Visible = true;
                        // Form2.GetInstance().label6.ForeColor = Color.OrangeRed;
                        // Form2.GetInstance().label6.Text = "数据库更新失败！";
                    }
                    new Thread(new ThreadStart(() =>
                    {
                        Thread.Sleep(3000);
                        if (ProMemory.formType == "1")
                            Form1.GetInstance().panel1.Visible = false;
                        else if (ProMemory.formType == "2")
                            Form2.GetInstance().panel1.Visible = false;

                    })).Start();
                    LogHelper.WriteLog(MethodBase.GetCurrentMethod().DeclaringType, "数据库更新失败");
                }
                isWait = false;
                resultRealTime = re;
            }
        }
        
        /// <summary>
        /// 不做catch处理，需要在外部做
        /// </summary>
        /// <param name="url"></param>
        /// <param name="method">默认GET，空则补充为GET</param>
        /// <param name="contenttype">默认json，空则补充为json</param>
        /// <param name="header">请求头部</param>
        /// <param name="data">请求body内容</param>
        /// <returns></returns>
        public void Http(string url, Hashtable header = null, string data = null)
        {
            string contenttype = "application/json;charset=utf-8";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = string.IsNullOrEmpty(contenttype) ? "application/json;charset=utf-8" : contenttype;
            if (header != null)
            {
                foreach (var i in header.Keys)
                {
                    request.Headers.Add(i.ToString(), header[i].ToString());
                }
            }
            if (!string.IsNullOrEmpty(data))
            {
                Stream RequestStream = request.GetRequestStream();
                byte[] bytes = Encoding.UTF8.GetBytes(data);
                RequestStream.Write(bytes, 0, bytes.Length);
                RequestStream.Close();
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream ResponseStream = response.GetResponseStream();
            StreamReader StreamReader = new StreamReader(ResponseStream, Encoding.GetEncoding("utf-8"));
            string re = StreamReader.ReadToEnd();
            StreamReader.Close();
            ResponseStream.Close();

        }

    }
}