using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using DBFactory;
using CommonLib;
using System.Threading;
namespace WcfControlMonitorLib
{
    /// <summary>
    /// Creator:Richard.liu
    /// 动态计算路径可用状态
    /// </summary>
    public static class CParsePLCData
    {
        public static event RefreshMonitorEventHandler RefreshMonitor;
        public static void OnRefreshMonitor(RefreshMonitorEventArgs e)
        {
            if (RefreshMonitor != null)
            {
                RefreshMonitor(e);
            }
        }
        public static event CDeviceStateChangeEventHandler DeviceStateChange;
        public static void OnDeviceStateChange(object sender,CDeviceStateChangeEventArgs e)
        {
            if (DeviceStateChange != null)
            {
                DeviceStateChange(sender, e);
            }
        }
       
        static StringBuilder sql = new StringBuilder();
        
        static string _CParsePLCError = "";//监控调度类错误说明

        public static string CParsePLCError
        {
            get { return _CParsePLCError; }
            set { _CParsePLCError = value; }
        }
        public  class AltDeviceInfos
        {
            public int DeviceIndex;
            public int DeviceKind;
            public int RunState;
            public int TaskNo;
            public int ErrorCode;
        }
        static DBOperator dbo =new DBOperator();//20130926
        static DBOperator dboMan = CStaticClass.dboM;//20130926
        static Dictionary<int,AltDeviceInfos> _modifyPathDeviceInfo;
        
        static object lockThis = new object();
        /// <summary>
        /// 添加可以改道设备信息
        /// </summary>
        public static void AddModifyPathDeviceInfo()
        {

            lock (lockThis)
            {
                DataView dv1 = new DataView();
                _modifyPathDeviceInfo = new Dictionary<int,AltDeviceInfos>();
                sql.Remove(0, sql.Length);
                sql.Append("select * from T_Base_Device where (F_DeviceKindIndex=1 or F_DeviceKindIndex=2 or F_DeviceKindIndex=4) and F_DBW2Address is not null order by F_DeviceIndex asc");//20130226richard.liu
                DataView dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                for (int i = 0; i < dv.Count; i++)
                {
                    AltDeviceInfos devinfo = new AltDeviceInfos();
                    devinfo.DeviceIndex = Convert.ToInt32(dv[i]["F_DeviceIndex"]);
                    devinfo.DeviceKind = Convert.ToInt32(dv[i]["F_DeviceKindIndex"]);
                    
                    if (_modifyPathDeviceInfo.ContainsKey(Convert.ToInt32(dv[i]["F_DeviceIndex"])) == false)
                    {
                        _modifyPathDeviceInfo.Add(Convert.ToInt32(dv[i]["F_DeviceIndex"]), devinfo);
                    }

                }
            }
        }
        public static void SetModifyPathDeviceInfo(int devindex,AltDeviceInfos altdev)
        {
            lock (lockThis)
            {
                _modifyPathDeviceInfo[devindex].ErrorCode = altdev.ErrorCode;
                _modifyPathDeviceInfo[devindex].RunState = altdev.RunState;
                _modifyPathDeviceInfo[devindex].TaskNo = altdev.TaskNo;
            }
        }
        
        //static Thread mythreadRoute;
        static Thread mythread;
        static bool exitThread = false;//20091107
        private static void BeginListen()
        {//20091107
            while (!exitThread  )
            {
                try
                {
                    lock (lockThis)
                    {//20130226richard.liu
                        SetDeviceState();
                    }
                }
                catch (Exception ex)
                {
                    _CParsePLCError =ex.StackTrace+ ex.Message;
                }
                finally
                {
                   Thread.Sleep(2000);
                }
            }
        }
        
        public static void EndListen()
        {//20091107
            exitThread = true;

            if (mythread != null)
            {

                mythread.Abort();
                mythread = null;
            }
            
            
        }
        public static void StartListen()
        {
            AddModifyPathDeviceInfo();
            //20091107
            exitThread = false;
            mythread = new Thread(new ThreadStart(BeginListen));
            mythread.IsBackground = true;
            mythread.Start();
            
        }
        
        /// <summary>
        /// 取得指定设备索引的设备状态:[0]读写标志;[1]状态;[2]任务号;[3]X坐标;[4]Y坐标;[5]设备索引
        /// </summary>
        /// <param name="deviceIdx">设备索引</param>
        /// <returns></returns>

        public static int[] GetModifyPathDeviceState(int deviceIdx)
        {
            int[] states = new int[6] { 1, 0, 0, 0, 0, deviceIdx };
            Model.MDevice  mdevinfo = Model.CGetInfo.GetModifyPathDeviceInfo(deviceIdx);
            if (mdevinfo != null)
            {
                states[1] = mdevinfo.ErrorCode;
                states[2] = mdevinfo.TaskNo;
                
                return states;
            }
            else
            {
                return null;
            }
           
        }


        /// <summary>
        /// 设置所有设备的当前动态属性
        /// </summary>
        public static void SetDeviceState()
        {
            DataView dvv = new DataView();
            DataView dv = new DataView();//20130306richard.liu
            try
            {
                //如果运行程序后,在10秒钟以内打开命令开关updateroute = false,如果在10秒钟之后打开命令开关updateroute = true;,可以在打开命令开关时CStaticClass.routetime = DateTime.Now;
                bool updateroute = false;
                if (CStaticClass.routetime.AddSeconds(10) <= DateTime.Now)
                {
                    updateroute = true;
                    CStaticClass.routetime = DateTime.Now;
                }
                sql.Remove(0, sql.Length);//20130306richard.liu
                sql.Append("SELECT F_DeviceIndex FROM T_Base_Device WHERE (F_LockedState = - 1) and (F_DeviceKindIndex=1 or F_DeviceKindIndex=2 or F_DeviceKindIndex=4) and F_DBW2Address is not null");//20130306richard.liu
                dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;//20130306richard.liu
                dv.Sort = "F_DeviceIndex";//20130306richard.liu
                int[] States;
                foreach (int devindex in _modifyPathDeviceInfo.Keys)
                {
                   
                    AltDeviceInfos devinfo1 = _modifyPathDeviceInfo[devindex];
                    //if (devinfo1.DeviceKind >= 6 && devinfo1.DeviceKind <= 30) continue;//20130226richard.liu

                    #region 设备被停用
                    //20130306richard.liu
                    if (dv.Find(devindex) >= 0)//20130306richard.liu
                    {
                        if (updateroute == true)
                        {//20100131
                            UpdateErrorCode(devinfo1.DeviceIndex, 998);
                            AlterRoute(devinfo1.DeviceIndex, 998);
                        }
                        //20090926
                        if (devinfo1.ErrorCode != 998)
                        {
                            UpdateErrorCode(devinfo1.DeviceIndex, 998);
                            AlterRoute(devinfo1.DeviceIndex, 998);
                            devinfo1.RunState = 4;

                        }
                        devinfo1.ErrorCode = 998;
                    }

                    #endregion

                    else
                    {
                        #region 输送机类

                        if (devinfo1.DeviceKind == 2)//20130226richard.liu
                        {
                            {
                                States = GetModifyPathDeviceState(devinfo1.DeviceIndex);
                                if (States == null) continue;

                                if (States[1] >= 30)
                                {
                                    if (updateroute == true)
                                    {//20100131
                                        UpdateErrorCode(devinfo1.DeviceIndex, States[1]);
                                        AlterRoute(devinfo1.DeviceIndex, States[1]);
                                    }
                                    //20100131

                                    //修改路径表
                                    if (States[1] != devinfo1.ErrorCode)
                                    {
                                        UpdateErrorCode(devinfo1.DeviceIndex, States[1]);
                                        AlterRoute(devinfo1.DeviceIndex, States[1]);
                                    }

                                    devinfo1.ErrorCode = States[1];
                                    devinfo1.RunState = 2;
                                }

                                else if ((States[1] == 0) || (States[1] == 1) || (States[1] == 2))
                                {
                                    if (updateroute == true)
                                    {//20100131
                                        UpdateErrorCode(devinfo1.DeviceIndex, 0);
                                        AlterRoute(devinfo1.DeviceIndex, States[1]);
                                    }
                                    //20100131

                                    //修改路径表
                                    if (States[1] != devinfo1.ErrorCode)
                                    {
                                        UpdateErrorCode(devinfo1.DeviceIndex, 0);
                                        AlterRoute(devinfo1.DeviceIndex, States[1]);
                                    }
                                    //20090926

                                    if (States[1] == 2)
                                    {
                                        //20090920
                                        devinfo1.RunState = 5;
                                    }
                                    else
                                    {
                                        devinfo1.RunState = States[1];
                                    }
                                    //20100131


                                    //20091006
                                    devinfo1.ErrorCode = States[1];
                                    //20090926
                                }
                                devinfo1.TaskNo = States[2];
                                //20101118

                            }

                        }

                        #endregion

                        #region 移动设备类

                        if ((devinfo1.DeviceKind == 1) || (devinfo1.DeviceKind == 4))
                        {
                            States = GetModifyPathDeviceState(devinfo1.DeviceIndex);

                            if (States == null) continue;


                            if (States[1] >= 30)
                            {
                                if (updateroute == true)
                                {//20100131
                                    UpdateErrorCode(devinfo1.DeviceIndex, States[1]);
                                    AlterRoute(devinfo1.DeviceIndex, States[1]);
                                }
                                //修改路径表
                                if (States[1] != devinfo1.ErrorCode)
                                {
                                    //20100131
                                    UpdateErrorCode(devinfo1.DeviceIndex, States[1]);
                                    AlterRoute(devinfo1.DeviceIndex, States[1]);
                                }
                                devinfo1.ErrorCode = States[1];
                                devinfo1.RunState = 2;
                            }
                            else if ((States[1] == 0) || (States[1] == 1) || (States[1] == 2))
                            {
                                if (updateroute == true)
                                {//20100131
                                    UpdateErrorCode(devinfo1.DeviceIndex, 0);
                                    AlterRoute(devinfo1.DeviceIndex, States[1]);
                                }
                                //修改路径表
                                if (States[1] != devinfo1.ErrorCode)
                                {
                                    //20100131
                                    UpdateErrorCode(devinfo1.DeviceIndex, 0);
                                    AlterRoute(devinfo1.DeviceIndex, States[1]);
                                }
                                //20090926

                                if (States[1] == 2)
                                {
                                    //20090920
                                    devinfo1.RunState = 5;
                                }
                                else
                                {
                                    devinfo1.RunState = States[1];
                                }
                                //20100131
                                devinfo1.ErrorCode = States[1];

                            }
                            devinfo1.TaskNo = States[2];
                            

                        }

                        #endregion

                    }
                    SetModifyPathDeviceInfo(devindex, devinfo1);
                }
            }

            catch (Exception exa)
            {

                _CParsePLCError = string.Format("解析PLC反馈数据的记录设备状态时发生错误:{0}", exa.StackTrace+exa.Message );
                RefreshMonitorEventArgs rmea = new RefreshMonitorEventArgs("tsStatus", _CParsePLCError);
                OnRefreshMonitor(rmea);
            }
            finally
            {
                dvv.Dispose();
            }
        }
       
        /// <summary>
        /// 修改本地路径表、反馈给管理的路径表
        /// </summary>
        /// <param name="devInx">发生故障的设备索引</param>
        /// <returns></returns>
        public static bool AlterRoute(int devInx, int state)
        {

            DataView dvr = new DataView(); DataView dv1 = new DataView(); DataView dv = new DataView();
            try
            {
                #region 根据堆垛机修改管理巷道是否可用
                //if ((devInx >= 11001) && (devInx <= 11003))
                //{//20110405表名:WH_LANEWAY 字段:WAREHOUSE_CODE:仓库编码-01、03、04 LANEWAY_CODE:巷道编码-1、2、3 
                //    //DEVICE_FLAG:设备状态-0=不可用;1=可用
                //    string LANEWAY_CODE = devInx.ToString().Substring(4,1);
                //    int DEVICE_FLAG=-1;
                //    if (state >= 30)
                //    {
                //        DEVICE_FLAG =0;
                //    }
                //    else
                //    {
                //        DEVICE_FLAG =1;
                //    }
                //    sql.Remove(0, sql.Length);
                //    sql.Append("update WH_LANEWAY set DEVICE_FLAG=").Append(DEVICE_FLAG).Append(" where WAREHOUSE_CODE='01' and LANEWAY_CODE='").Append(LANEWAY_CODE).Append("' and DEVICE_FLAG<>").Append(DEVICE_FLAG);
                //    dboMan.ExceSQL(sql.ToString());

                //}
                #endregion
                sql.Remove(0, sql.Length);
                sql.Append("select distinct F_RouteID from T_Base_Route_Device where F_DeviceOrder>0 and F_DeviceIndex=").Append(devInx);
                dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                for (int i = 0; i < dv.Count; i++)
                {
                    if (state >= 30)
                    {
                        //所有子路径都不可用时,方才设定此路径真的不可用
                        sql.Remove(0, sql.Length);
                        sql.Append(" SELECT T_Base_Route_Device.F_RouteIDSub, SUM(T_Base_Device.F_ErrorCode) AS ErrorCodes ").Append(
                                    " FROM T_Base_Route_Device,T_Base_Device where (F_DeviceKindIndex=1 or F_DeviceKindIndex=2 or F_DeviceKindIndex=4) and F_DBW2Address is not null and F_DeviceOrder >0 and T_Base_Route_Device.F_DeviceIndex = T_Base_Device.F_DeviceIndex").Append(
                                    " and T_Base_Route_Device.F_RouteID=").Append(dv[i]["F_RouteID"]).Append(" GROUP BY T_Base_Route_Device.F_RouteIDSub ");//20130226richard.liu
                        dvr = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                        bool ifUsable = false;
                        for (int kk = 0; kk < dvr.Count; kk++)
                        {
                            if (Convert.ToInt32(dvr[kk]["ErrorCodes"]) <= 0)
                            {
                                ifUsable = true;
                                break;
                            }
                        }
                        if (ifUsable == false)
                        {
                            //20101011
                            sql.Remove(0, sql.Length);
                            sql.Append("update t_base_route set F_Status=0 where f_routeid=").Append(dv[i]["F_RouteID"]).Append(" and F_Status=1 and F_AutoUpdate=1 ");
                            int ups = dbo.ExecuteSql(sql.ToString());
                            sql.Remove(0, sql.Length);
                            sql.Append("update IO_CONTROL_ROUTE set CONTROL_ROUTE_STATUS=0 where CONTROL_ROUTE_ID='").Append(dv[i]["F_RouteID"]).Append("' and CONTROL_ROUTE_STATUS=1");
                            if (ups > 0) dboMan.ExceSQL(sql.ToString());
                        }
                        else
                        {
                            //20120328有一条子路径可用,路径就可用
                            sql.Remove(0, sql.Length);
                            sql.Append("update t_base_route set F_Status=1 where f_routeid=").Append(dv[i]["F_RouteID"]).Append(" and F_Status=0 and F_AutoUpdate=1 ");
                            int ups = dbo.ExecuteSql(sql.ToString());
                            sql.Remove(0, sql.Length);
                            sql.Append("update IO_CONTROL_ROUTE set CONTROL_ROUTE_STATUS=1 where CONTROL_ROUTE_ID='").Append(dv[i]["F_RouteID"]).Append("' and CONTROL_ROUTE_STATUS=0");
                            if (ups > 0) dboMan.ExceSQL(sql.ToString());
                        }

                    }
                    else
                    {
                        sql.Remove(0, sql.Length);
                        sql.Append("SELECT SUM(T_Base_Device.F_ErrorCode) as errcode FROM T_Base_Device ,T_Base_Route_Device").Append(
                            " where  (F_DeviceKindIndex=1 or F_DeviceKindIndex=2 or F_DeviceKindIndex=4) and F_DBW2Address is not null and F_DeviceOrder>0 and T_Base_Device.F_DeviceIndex = T_Base_Route_Device.F_DeviceIndex and T_Base_Route_Device.F_RouteID=").Append(dv[i]["F_RouteID"]);//20130226richard.liu
                        dv1 = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                        if (dv1.Count > 0)
                        {
                            int errcode = 0; int a = 0;
                            if (int.TryParse(dv1[0]["errcode"].ToString(), out a) == true)
                            {
                                errcode = Convert.ToInt32(dv1[0]["errcode"]);
                            }

                            if (errcode <= 0)
                            {
                                //20101011
                                sql.Remove(0, sql.Length);
                                sql.Append("update t_base_route set F_Status=1 where f_routeid=").Append(dv[i]["F_RouteID"]).Append(" and F_Status=0 and F_AutoUpdate=1 ");
                                int ups = dbo.ExecuteSql(sql.ToString());
                                sql.Remove(0, sql.Length);
                                sql.Append("update IO_CONTROL_ROUTE set CONTROL_ROUTE_STATUS=1 where CONTROL_ROUTE_ID='").Append(dv[i]["F_RouteID"]).Append("' and CONTROL_ROUTE_STATUS=0");
                                if (ups > 0) dboMan.ExceSQL(sql.ToString());
                            }
                        }


                    }
                }


                return true;
            }
            catch (Exception ex)
            {
                _CParsePLCError = string.Format("解析PLC反馈数据的修改路径时发生错误:{0}", ex.StackTrace+ex.Message );
                RefreshMonitorEventArgs rmea = new RefreshMonitorEventArgs("tsStatus", _CParsePLCError);
                OnRefreshMonitor(rmea);
                return false;
            }
            finally
            {
                dv.Dispose();
                dvr.Dispose();
                dv1.Dispose();
            }
        }
        static void UpdateErrorCode(int devInx, int errorCode)
        {
            #region 原来的程序
            ////20130226richard.liu
            //sql.Clear();
            //sql.Append("SELECT F_DeviceErrorIndex FROM T_Base_Device_State where F_DeviceKindIndex=").Append(_modifyPathDeviceInfo[devInx].DeviceKind).Append(" and F_DeviceErrorIndex=").Append(errorCode);
            //DataView dv = dbo.程序ExceSQL(sql.ToString()).Tables[0].DefaultView;
            //if (dv.Count > 0)
            //{
            //    sql.Clear();
            //    sql.Append("UPDATE T_Base_Device SET F_ErrorCode = ").Append(errorCode).Append(" WHERE (F_DeviceIndex = ").Append(devInx).Append(")and (F_ErrorCode <> ").Append(errorCode).Append(")");
            //    CStaticClass.dbo.ExecuteSql(sql.ToString());//20130306richard.liu使用主线程数据连接修改,以免造成UPDATE并发
            //}
            //dv.Dispose(); 
            #endregion
            DataView dv = new DataView();
            int errorindex = 0;
            try
            {
                //if (devInx == 14102)
                //{
                //}
                string sqlstr = string.Format("SELECT F_DeviceIndex,F_ErrorTaskNo,F_ErrorCode  FROM T_Base_Device where F_DeviceIndex={0} and F_ErrorCode!={1}", devInx, errorCode);//查找故障设备
                dv = dbo.ExceSQL(sqlstr).Tables[0].DefaultView;
                //sql.Append("SELECT F_DeviceErrorIndex FROM T_Base_Device_State where F_DeviceKindIndex=").Append(_modifyPathDeviceInfo[devInx].DeviceKind).Append(" and F_DeviceErrorIndex=").Append(errorCode);

                if (dv.Count > 0)//状态发生变化之后才更新状态
                {

                    if (errorCode > 0)
                    {
                        Model.MError errs = Model.CGetInfo.GetErrorInfo(Convert.ToInt32(_modifyPathDeviceInfo[devInx].DeviceKind + errorCode.ToString()));
                        if (errs == null)
                        {
                            return;
                        }
                        errorindex = errs.ErrorIndex;
                    }



                    //int taskno = Convert.ToInt32(dv[0]["F_ErrorTaskNo"]);

                    string str = string.Empty;
                    if (errorCode == 0)
                    {
                        str = string.Format(",F_ErrorTaskNo=0 ");
                    }
                    sqlstr = string.Format("UPDATE T_Base_Device SET F_ErrorCode = {0}{1} WHERE (F_DeviceIndex = {2})and (F_ErrorCode <> {3})", errorCode, str, devInx, errorCode);

                    //sql.Clear();
                    //sql.Append("UPDATE T_Base_Device SET F_ErrorCode = ").Append(errorCode).Append(" WHERE (F_DeviceIndex = ").Append(devInx).Append(")and (F_ErrorCode <> ").Append(errorCode).Append(")");
                    int count = CStaticClass.dbo.ExecuteSql(sqlstr);//20130306richard.liu使用主线程数据连接修改,以免造成UPDATE并发

                    if (count > 0) //故障解除时记录故障结束时间
                    {
                        string dtime = DateTime.Now.ToString("u");//20110603

                        dtime = dtime.Substring(0, dtime.Length - 1);

                        //新的故障发生时,先更改上一个故障的结束时间
                        //sqlstr = string.Format("UPDATE T_Base_Device_Error_Log SET F_End_DateTime ='{0}' Where F_End_DateTime is null and F_DeviceIndex={1}  and  F_MonitorIndex = {2} ", dtime, devInx, taskno);
                        sqlstr = string.Format("UPDATE T_Base_Device_Error_Log SET F_End_DateTime ='{0}' Where F_End_DateTime is null and F_DeviceIndex={1}  ", dtime, devInx);

                        CStaticClass.dbo.ExecuteSql(sqlstr);//20130306richard.liu使用主线程数据连接修改,以免造成UPDATE并发
                        
                        //新的故障发生,记录
                        if (errorCode != 0 && errorCode != 998)//设备被禁用以后,也认为是无故障  
                        {
                            int taskno = _modifyPathDeviceInfo[devInx].TaskNo;
                            sqlstr = string.Format("INSERT INTO T_Base_Device_Error_Log (F_TaskNo,F_DeviceIndex, F_ErrorIndex, F_DateTime) VALUES ({0},{1},{2},'{3}')", taskno, devInx, errorindex, dtime);

                            CStaticClass.dbo.ExecuteSql(sqlstr);//20130306richard.liu使用主线程数据连接修改,以免造成UPDATE并发

                            //sql.Remove(0, sql.Length);
                            //sql.Append("INSERT INTO T_Base_Device_Error_Log (F_ManageTaskNo,F_DeviceIndex, F_ErrorIndex, F_DateTime) VALUES (").Append(fid).Append(",").Append(DeviceIdx).Append(",").Append(errs.ErrorIndex).Append(",'").Append(dtime).Append("')");
                            //dbo.ExceSQL(sql.ToString());
 
                        }
                        



                    }

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally 
            {
                dv.Dispose();
            }

        }
        
    }
}