using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using QMAPP.FJC.TRACING.DAInterface;
using QMAPP.FJC.Entity.QT;
using QMAPP.FJC.DAL.QT;
using QMAPP.BLL;
using QMAPP.MD.DAL;
using QMAPP.FJC.Entity.Basic;
using QMFrameWork.Log;

namespace QMAPP.FJC.TRACING.DAHandler
{
    /// <summary>
    /// 数据获取类
    /// </summary>
    public class DataAcquirer : BaseBLL
    {
        #region 静态字段
        /// <summary>
        /// 数据解析类列表
        /// </summary>
        static Dictionary<string, Analyzer> _AnalyzerList;
        /// <summary>
        /// 数据解析类列表
        /// </summary>
        static List<Validator> _ValidatorList;
        /// <summary>
        /// 状态动作列表
        /// </summary>
        static Dictionary<string, StateAction> _StateActionList;
        #endregion

        /// <summary>
        /// 输入数据
        /// </summary>
        /// <param name="workcellcode">工序编码</param>
        /// <param name="workloccode">工位编码</param>
        /// <param name="dacode">采集点编码</param>
        /// <param name="davalue">采集值</param>
        /// <returns>返回采集结果</returns>
        public DAResult Input(DAArgs Args)
        {
            DAResult result = new DAResult();
            result.MouldCode = Args.MouldCode;
            DAObject data = null;
            StringBuilder log = new StringBuilder();
            try
            {
                
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                log.AppendFormat("{0},{1},{2}\t", Args.WorkLocCode, Args.DACode, Args.DAValue);
                stopwatch.Start();
                //初始化采集数据对象
                data = InitDAObject(Args);

                stopwatch.Stop();
                log.AppendFormat("INITDA:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                AnalyzeData(data);//解析数据

                stopwatch.Stop();
                log.AppendFormat("ANADA:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                data.WorkLocState.LoadState(data.MouldCode);

                stopwatch.Stop();
                log.AppendFormat("LOADCH:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                if (data.OrderPlan == null)
                {
                    if (!string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.ORDERPLAN_PID))
                    {
                        //DAL.FIS.OrderPlanDAL orderplandal = new DAL.FIS.OrderPlanDAL();
                        //data.OrderPlan = orderplandal.Get(new Entity.FIS.OrderPlan { PID = data.WorkLocState.CurrentState.ORDERPLAN_PID });
                        DAL.ProductionPlan.WorkOrderDAL workorderdal = new DAL.ProductionPlan.WorkOrderDAL();
                        data.OrderPlan = workorderdal.GetOneByID(data.WorkLocState.CurrentState.ORDERPLAN_PID);
                    }
                }
                if (data.OrderPlan != null)
                {
                    data.WorkLocState.CurrentState.ORDERPLAN_PID = data.OrderPlan.PID;
                }
                result.MouldCode = data.MouldCode;

                //工序状态与采集点工序状态是否匹配
                if (!string.IsNullOrWhiteSpace(data.DAI.STATE_CODE) && !string.Equals(data.DAI.STATE_CODE, data.WorkLocState.CurrentState.STATE_CODE))
                {
                    if (string.Equals(data.DAI.CANPREINPUT, "1"))
                    {
                        return PreInput(data);
                    }
                    else
                    {
                        result.Message = string.Format("当前状态“{0}”,无法接收“{1}”输入!", data.WorkLocState.CurrentState.STATE_NAME, data.DAI.DA_NAME);
                        return result;
                    }
                }

                if (!(string.Equals(data.DAI.DA_MODE, "3") || string.Equals(data.DAI.DA_MODE, "5")) && data.WorkLocState.DataCache.Count(p => p.DA_MODE == "3" || p.DA_MODE == "5") > 0)//如果当前采集项不是自适应项并且采集点列表中包含自适应项
                {
                    LoadAdaptiveDA(data);
                }

                stopwatch.Stop();
                log.AppendFormat("CHECKDA:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                var vresult = ValidateData(data);//校验数据

                stopwatch.Stop();
                log.AppendFormat("VALIDDA:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                if (!vresult.Passed)//验证未通过
                {
                    result.Message = vresult.Message;
                    return result;
                }
                if (string.Equals(data.DAI.DA_MODE, "3") || string.Equals(data.DAI.DA_MODE, "5")) //如果为自适应项
                {
                    SaveAdaptiveMaterial(data);
                }
                SetDACache(data);//设置数据采集缓存

                stopwatch.Stop();
                log.AppendFormat("SETCH:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                CheckState(data, result);//检查状态变化

                stopwatch.Stop();
                log.AppendFormat("STCHANGE:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                

                data.DataSession.OpenTs();//开启事务
                data.PersistEntitys();
                data.ExcuteSQL();
                data.DataSession.CommitTs();//提交事务

                stopwatch.Stop();
                log.AppendFormat("EXECSQL:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                result.StateName = data.WorkLocState.CurrentState.STATE_NAME;
                result.StateCode = data.WorkLocState.CurrentState.STATE_CODE;
                //2017-10-1 闫永刚
                result.MATERIAL_CODE = data.MaterialCode;
                result.MATERIAL_NAME = data.MaterialName;
                result.WorkOrderID = data.WorkOrderID;
                result.AnalyzedValue = data.AnalyzedValue;
                result.Success = true;

                stopwatch.Stop();
                log.AppendFormat("END:{0}ms\t", stopwatch.ElapsedMilliseconds);
                stopwatch.Start();

                return result;
            }
            catch (Exception ex)
            {
                if (data != null)
                {
                    data.DataSession.RollbackTs();//回滚事务
                }
                result.Message = ex.Message;
                return result;
            }
            finally
            {
                log.Append(result.Message);
                LogManager.LogHelper.Debug(new LogInfo()
                {
                    Info = log.ToString(),
                });
            }
        }
        /// <summary>
        /// 保存采集模式为自适应的上料信息
        /// </summary>
        /// <param name="data"></param>
        private static void SaveAdaptiveMaterial(DAObject data)
        {
            DAL.Produce.ProductDAL pdal = new DAL.Produce.ProductDAL();
            var product = pdal.GetByPID(data.ObjectPID);
            product.WORKLOC_CODE = data.WorkLocState.WORKLOC_CODE;
            //查找之前使用的上料信息
            var usingmaterial = pdal.GetUsingMaterial(data.WorkLocState.WORKLOC_CODE).FirstOrDefault(p => p.MATERIAL_CODE == product.MATERIAL_CODE);
            if (usingmaterial != null && !string.Equals(usingmaterial.PID, product.PID))
            {
                usingmaterial.WORKLOC_CODE = "";
                data.AddToPersistentList(usingmaterial, usingmaterial.PID);
            }
            data.AddToPersistentList(product, product.PID);
        }

        /// <summary>
        /// 回滚/撤销
        /// </summary>
        /// <returns></returns>
        public DAResult Rollback(DAArgs Args)
        {
            DAResult result = new DAResult();
            DAObject data = null;
            try
            {
                //初始化无采集点对象的
                data = InitDAObjectForPass(Args);
                data.WorkLocState.LoadState(Args.MouldCode);
                result.MouldCode = data.MouldCode;
                ////判断是否已生成产品数据
                //if (string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.PROCESS_CODE))
                //{
                //    throw new Exception(string.Format("当前状态“{0}”,无法执行撤销操作!", data.WorkLocState.CurrentState.STATE_NAME));
                //}
                //StateActions.RollbackWithOrder rollback = new StateActions.RollbackWithOrder(); //执行数据回滚动作
                //rollback.Execute(data);
                //StateActions.ResetData resetdata = new StateActions.ResetData(); //执行数据复位
                //resetdata.Execute(data);
                if (string.Equals(data.WorkLocState.CurrentState.ROLLBACK_ACTION, "N/A"))
                {
                    throw new Exception(string.Format("当前状态“{0}”,无法执行撤销操作!", data.WorkLocState.CurrentState.STATE_NAME));
                }
                foreach (var action in data.WorkLocState.CurrentState.ROLLBACK_ACTION.Split(';'))//执行放行动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                }


                result.StateChanged = true;
                SetToFirstState(data);
                foreach (var action in data.WorkLocState.CurrentState.ENTRY_ACTION.Split(';'))//执行进入状态动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                }
                CheckState(data, result);
                data.DataSession.OpenTs();//开启事务
                data.PersistEntitys();
                data.ExcuteSQL();
                data.DataSession.CommitTs();//提交事务
                result.StateName = data.WorkLocState.CurrentState.STATE_NAME;
                result.StateCode = data.WorkLocState.CurrentState.STATE_CODE;
                result.Success = true;
                
                return result;
            }
            catch (Exception ex)
            {
                if (data != null)
                {
                    data.DataSession.RollbackTs();//回滚事务
                }
                result.Message = ex.Message;
                return result;
            }
        }

        /// <summary>
        /// 重置
        /// </summary>
        /// <returns></returns>
        public DAResult Reset(DAArgs Args)
        {
            DAResult result = new DAResult();
            DAObject data = null;
            try
            {
                //初始化无采集点对象的
                data = InitDAObjectForPass(Args);
                data.WorkLocState.LoadState(Args.MouldCode);
                result.MouldCode = data.MouldCode;
                //判断是否已生成产品数据
                //if (!string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.PROCESS_CODE))
                //{
                //    throw new Exception(string.Format("当前状态“{0}”,无法执行重置操作!", data.WorkLocState.CurrentState.STATE_NAME));
                //}
                //StateActions.ResetData resetdata = new StateActions.ResetData(); //执行数据复位
                //resetdata.Execute(data);
                if (string.Equals(data.WorkLocState.CurrentState.RESET_ACTION, "N/A"))
                {
                    throw new Exception(string.Format("当前状态“{0}”,无法执行复位操作!", data.WorkLocState.CurrentState.STATE_NAME));
                }
                foreach (var action in data.WorkLocState.CurrentState.RESET_ACTION.Split(';'))//执行放行动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                }

                result.StateChanged = true;
                SetToFirstState(data);
                foreach (var action in data.WorkLocState.CurrentState.ENTRY_ACTION.Split(';'))//执行进入状态动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                }
                data.DataSession.OpenTs();//开启事务
                data.PersistEntitys();
                data.ExcuteSQL();
                data.DataSession.CommitTs();//提交事务
                result.StateName = data.WorkLocState.CurrentState.STATE_NAME;
                result.StateCode = data.WorkLocState.CurrentState.STATE_CODE;
                result.Success = true;

                return result;
            }
            catch (Exception ex)
            {
                if (data != null)
                {
                    data.DataSession.RollbackTs();//回滚事务
                }
                result.Message = ex.Message;
                return result;
            }
        }

        /// <summary>
        /// 放行
        /// </summary>
        /// <param name="Args"></param>
        /// <returns></returns>
        public DAResult LetPass(DAArgs Args)
        {
            DAResult result = new DAResult();
            DAObject data = null;
            try
            {
                //初始化无采集点对象的
                data = InitDAObjectForPass(Args);
                data.WorkLocState.LoadState(Args.MouldCode);

                if (data.OrderPlan == null)
                {
                    if (!string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.ORDERPLAN_PID))
                    {
                        //DAL.FIS.OrderPlanDAL orderplandal = new DAL.FIS.OrderPlanDAL();
                        //data.OrderPlan = orderplandal.Get(new Entity.FIS.OrderPlan { PID = data.WorkLocState.CurrentState.ORDERPLAN_PID });
                        DAL.ProductionPlan.WorkOrderDAL workorderdal = new DAL.ProductionPlan.WorkOrderDAL();
                        data.OrderPlan = workorderdal.GetOneByID(data.WorkLocState.CurrentState.ORDERPLAN_PID);
                    }
                }
                if (data.OrderPlan != null)
                {
                    data.WorkLocState.CurrentState.ORDERPLAN_PID = data.OrderPlan.PID;
                }

                result.MouldCode = data.MouldCode;

                if (string.Equals(data.WorkLocState.CurrentState.MANUALPASS_ACTION, "N/A"))
                {
                    throw new Exception(string.Format("当前状态“{0}”,无法执行放行操作!", data.WorkLocState.CurrentState.STATE_NAME));
                }
                foreach (var action in data.WorkLocState.CurrentState.MANUALPASS_ACTION.Split(';'))//执行放行动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                }
                
                result.StateChanged = true;
                foreach (var action in data.WorkLocState.CurrentState.EXIT_ACTION.Split(';'))//执行退出状态动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                }
                SetToNextState(data);
                foreach (var action in data.WorkLocState.CurrentState.ENTRY_ACTION.Split(';'))//执行进入状态动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                }
                CheckState(data, result);
                data.DataSession.OpenTs();//开启事务
                data.PersistEntitys();
                data.ExcuteSQL();
                data.DataSession.CommitTs();//提交事务
                result.StateName = data.WorkLocState.CurrentState.STATE_NAME;
                result.StateCode = data.WorkLocState.CurrentState.STATE_CODE;
                result.Success = true;
                
                return result;
            }
            catch (Exception ex)
            {
                if (data != null)
                {
                    data.DataSession.RollbackTs();//回滚事务
                }
                result.Message = ex.Message;
                return result;
            }
        }
        /// <summary>
        /// 提前输入
        /// </summary>
        /// <param name="Args"></param>
        /// <returns></returns>
        public DAResult PreInput(DAObject data)
        {
            data.PreInput = true;
            DAResult result = new DAResult();
            result.PreInput = true;
            try
            {
                var percache= LoadPreInputCache(data);
                
                foreach (var pre in percache)
                {
                    var cache = data.WorkLocState.DataCache.FirstOrDefault(p => p.DA_CODE == pre.DA_CODE);
                    if (cache != null)
                    {
                        cache.DA_CODE = pre.DA_CODE;
                        cache.DA_SEQ = pre.DA_SEQ;
                        cache.DA_STATE = pre.DA_STATE;
                        cache.DA_VALUE = pre.DA_VALUE;
                        cache.OBJ_PID = pre.OBJ_PID;
                        cache.DATA_TYPE = pre.DATA_TYPE;
                        cache.MATERIAL_CODE = pre.MATERIAL_CODE;
                        cache.DA_MODE = pre.DA_MODE;
                        cache.DA_NAME = pre.DA_NAME;
                        cache.PIVOTAL = pre.PIVOTAL;
                        cache.ISPROCESSCODE = pre.ISPROCESSCODE;
                        cache.MATERIAL_TYPE = pre.MATERIAL_TYPE;
                        cache.PID = pre.PID;
                        cache.STATE_CODE = pre.STATE_CODE;
                        cache.WORKCELL_CODE = pre.WORKCELL_CODE;
                        cache.WORKLOC_CODE = data.WorkLocState.WORKLOC_CODE;
                        cache.PREINPUT = pre.PREINPUT;
                        cache.IsNewInfo = pre.IsNewInfo;
                    }
                    else
                    {
                        data.WorkLocState.DataCache.Add(pre);
                    }
                }

                AnalyzeData(data);//解析数据

                //if (!string.Equals(data.DAI.DA_MODE, "3") && data.WorkLocState.DataCache.Count(p => p.DA_MODE == "3") > 0)//如果当前采集项不是自适应项并且采集点列表中包含自适应项
                //{
                //    LoadAdaptiveDA(data, false);
                //}
                if (!(string.Equals(data.DAI.DA_MODE, "3") || string.Equals(data.DAI.DA_MODE, "5")) && data.WorkLocState.DataCache.Count(p => p.DA_MODE == "3" || p.DA_MODE == "5") > 0)//如果当前采集项不是自适应项并且采集点列表中包含自适应项
                {
                    LoadAdaptiveDA(data);
                }

                var vresult = ValidateData(data);//校验数据
                if (!vresult.Passed)//验证未通过
                {
                    result.Message = vresult.Message;
                    return result;
                }
                //if (string.Equals(data.DAI.DA_MODE, "3")) //如果为自适应项
                //{
                //    SaveAdaptiveMaterial(data);
                //}
                if (string.Equals(data.DAI.DA_MODE, "3") || string.Equals(data.DAI.DA_MODE, "5")) //如果为自适应项
                {
                    SaveAdaptiveMaterial(data);
                }
                SetDACache(data);//设置数据采集缓存
                //CheckState(data, result);//检查状态变化
                data.DataSession.OpenTs();//开启事务
                data.PersistEntitys();
                data.DataSession.CommitTs();//提交事务
                result.StateName = data.WorkLocState.CurrentState.STATE_NAME;
                result.StateCode = data.WorkLocState.CurrentState.STATE_CODE;
                //2017-10-1 闫永刚
                result.MATERIAL_CODE = data.MaterialCode;
                result.MATERIAL_NAME = data.MaterialName;
                result.MouldCode = data.MouldCode;
                result.Success = true;
                

                return result;
            }
            catch (Exception ex)
            {
                if (data != null)
                {
                    data.DataSession.RollbackTs();//回滚事务
                }
                result.Message = ex.Message;
                return result;
            }
        }
        /// <summary>
        /// 加载提前扫描数据
        /// </summary>
        /// <param name="data"></param>
        private List<DAICache> LoadPreInputCache(DAObject data)
        {
            DAICacheDAL dal = new DAICacheDAL();
            var cachelist = dal.GetList(data.WorkLocState.WORKCELL_CODE, data.WorkLocState.WORKLOC_CODE).Where(p => string.Equals(p.PREINPUT, "1")).ToList();
            DAIDAL daidal = new DAIDAL();
            var predailist = daidal.GetList(data.WorkLocState.WORKCELL_CODE).Where(p => string.Equals(p.CANPREINPUT, "1")).ToList();

            DAL.Basic.MachineInfoDAL machinedal = new DAL.Basic.MachineInfoDAL();
            var machine= machinedal.GetMachineInfo(new MachineInfo { MACHINECODDE = data.MachineCode });
            if (machine.ISSTATION == 2)
            {
                cachelist = cachelist.Where(p => p.MOULD_CODE == data.MouldCode).ToList();
            }
 
            if (cachelist == null || cachelist.Count == 0)
            {
                cachelist = new List<DAICache>();
                foreach (var dai in predailist)
                {
                    cachelist.Add(new DAICache
                    {
                        DA_CODE = dai.DA_CODE,
                        DA_SEQ = dai.DA_SEQ,
                        DA_STATE = dai.DA_STATUS,
                        DA_VALUE = "",
                        OBJ_PID = "",
                        DATA_TYPE = dai.DATA_TYPE,
                        MATERIAL_CODE = "",
                        DA_MODE = dai.DA_MODE,
                        DA_NAME = dai.DA_NAME,
                        PIVOTAL = dai.PIVOTAL,
                        ISPROCESSCODE = dai.ISPROCESSCODE,
                        MATERIAL_TYPE = dai.MATERIAL_TYPE,
                        PID = Guid.NewGuid().ToString(),
                        STATE_CODE = dai.STATE_CODE,
                        WORKCELL_CODE = dai.WORKCELL_CODE,
                        WORKLOC_CODE = data.WorkLocState.WORKLOC_CODE,
                        UPDATEDATE = DateTime.Now,
                        PREINPUT = "1",
                        MOULD_CODE = data.MouldCode
                    });
                }
                dal.Insert(cachelist);
            }
            else if (cachelist.Count < predailist.Count)
            {
                foreach (var dai in predailist)
                {
                    if (!cachelist.Exists(p => p.DA_CODE == dai.DA_CODE))
                    {
                        cachelist.Add(new DAICache
                        {
                            DA_CODE = dai.DA_CODE,
                            DA_SEQ = dai.DA_SEQ,
                            DA_STATE = dai.DA_STATUS,
                            DA_VALUE = "",
                            OBJ_PID = "",
                            DATA_TYPE = dai.DATA_TYPE,
                            MATERIAL_CODE = "",
                            DA_MODE = dai.DA_MODE,
                            DA_NAME = dai.DA_NAME,
                            PIVOTAL = dai.PIVOTAL,
                            ISPROCESSCODE = dai.ISPROCESSCODE,
                            MATERIAL_TYPE = dai.MATERIAL_TYPE,
                            PID = Guid.NewGuid().ToString(),
                            STATE_CODE = dai.STATE_CODE,
                            WORKCELL_CODE = dai.WORKCELL_CODE,
                            WORKLOC_CODE = data.WorkLocState.WORKLOC_CODE,
                            UPDATEDATE = DateTime.Now,
                            PREINPUT = "1",
                            IsNewInfo = true,
                            MOULD_CODE = data.MouldCode
                        });
                    }
                }
                dal.Insert(cachelist.Where(p => p.IsNewInfo).ToList());
            }
            return cachelist;
        }

        #region 采集点数据初始化
        /// <summary>
        /// 初始化采集数据对象
        /// </summary>
        /// <returns></returns>
        private DAObject InitDAObject(DAArgs Args)
        {
            var workcell = new WorkCellDAL().GetWorkCellByCode(Args.WorkCellCode);
            if (workcell == null)
            {
                throw new Exception("无法根据输入信息找到工序!请检查工序设置。");
            }
            var dai = new DAIDAL().GetDAIByCode(Args.WorkCellCode, Args.DACode);
            if (dai == null)
            {
                throw new Exception("无法根据输入信息找到数据采集接口!请检查采集接口设置。");
            }
            dai.WORKLOC_CODE = Args.WorkLocCode;

            var shift = new FJC.BLL.Basic.ProduceShiftBLL().GetWorkingShift(workcell.WORKCENTER_CODE);
            

            int iscontrol = 0;
            int.TryParse(Args.IsControl, out iscontrol);
            //初始化采集数据对象
            DAObject data = new DAObject()
            {
                DAI = dai,
                WorkLocState = new WorkLocState(workcell, Args.WorkLocCode),
                DAValue = Args.DAValue,
                UserID = base.LoginUser.UserID,
                MaterialCode = Args.MaterialCode,
                MachineCode = Args.MachineCode,
                MachineName = Args.MachineName,
                IsControl = iscontrol,
                MouldCode = Args.MouldCode,
                Date = DateTime.Now,
                Shift = shift != null ? shift : new ProduceShift { PRODUCESHIFTTCODE="-" },
                AttachData=Args.AttachData,
                MouldReLocate=false
            };
            return data;
        }
        /// <summary>
        /// 初始化采集数据对象(无采集点对象)
        /// </summary>
        /// <param name="Args"></param>
        /// <returns></returns>
        private DAObject InitDAObjectForPass(DAArgs Args)
        {
            var workcell = new WorkCellDAL().GetWorkCellByCode(Args.WorkCellCode);
            if (workcell == null)
            {
                throw new Exception("无法根据输入信息找到工序!请检查工序设置。");
            }
            int iscontrol = 0;
            int.TryParse(Args.IsControl, out iscontrol);
            var shift = new FJC.BLL.Basic.ProduceShiftBLL().GetWorkingShift(workcell.WORKCENTER_CODE);
            //初始化采集数据对象
            DAObject data = new DAObject()
            {
                DAI = null,
                WorkLocState = new WorkLocState(workcell, Args.WorkLocCode),
                DAValue = Args.DAValue,
                UserID = base.LoginUser.UserID,
                MaterialCode = Args.MaterialCode,
                MachineCode = Args.MachineCode,
                MachineName = Args.MachineName,
                IsControl = iscontrol,
                MouldCode = Args.MouldCode,
                Date=DateTime.Now,
                Shift = shift != null ? shift : new ProduceShift { PRODUCESHIFTTCODE = "-" },
                AttachData = Args.AttachData,
                MouldReLocate = false
            };
            return data;
        }
        /// <summary>
        /// 加载自适应采集项
        /// </summary>
        /// <param name="data"></param>
        private void LoadAdaptiveDA(DAObject data, bool Persistent = true)
        {
            //提取采集数据中的物料号信息
            var materials = (from da in data.WorkLocState.DataCache
                             where !string.IsNullOrWhiteSpace(da.MATERIAL_CODE)
                                   && !string.Equals(da.DA_MODE, "2") //过滤掉可省略的采集点
                                   && !string.Equals(da.DA_MODE, "3") //过滤掉自适应采集点
                                   && !string.Equals(da.DA_MODE, "5") //过滤掉自适应采集点
                                   && !string.Equals(da.DA_CODE, data.DAI.DA_CODE) //过滤掉当前输入的采集点
                             select da.MATERIAL_CODE).ToList();
            PbomDAL dal = new PbomDAL();
            materials.Add(data.MaterialCode + "");
            var bomlocates = dal.LocateBom(materials.Distinct().ToArray()); //匹配物料BOM
            MD.Entity.View.BomLocation bomloc = null;
            if (bomlocates.Count>0)
            {
                if (data.OrderPlan != null)
                {
                    bomloc = bomlocates.FirstOrDefault(p => p.BOMCode == data.OrderPlan.PBOM_CODE);
                }
                else if(bomlocates.GroupBy(p=>p.UP_MATERIAL_CODE).ToList().Count==1)
                {
                    bomloc = bomlocates[0];
                }
            }
            if (bomloc != null) //如果存在匹配的BOM
            {
                var bomitems = dal.GetBomItemsByLocate(bomloc); //查找组成物料列表
                var adaptmaterials = (from bomtiem in bomitems
                                      select bomtiem.MATERIAL_CODE).ToArray();
                DAL.Produce.ProductDAL productdal = new DAL.Produce.ProductDAL();
                var adapts = productdal.GetUsingMaterial(data.WorkLocState.WORKLOC_CODE);
                foreach (var da in data.WorkLocState.DataCache.Where(p => p.DA_MODE == "3" || p.DA_MODE == "5"))
                {
                    var adaptmaterial = adapts.FirstOrDefault(p => adaptmaterials.Contains(p.MATERIAL_CODE) && (p.MATERIAL_TYPE == da.MATERIAL_TYPE || p.PARENT_MATERIAL_TYPE == da.MATERIAL_TYPE));
                    if (adaptmaterial != null)//找到匹配的物料
                    {
                        da.DA_VALUE = adaptmaterial.PRODUCTCODE;
                        da.MATERIAL_CODE = adaptmaterial.MATERIAL_CODE;
                        da.OBJ_PID = adaptmaterial.PID;
                    }
                    else
                    {
                        da.DA_VALUE = "";
                        da.MATERIAL_CODE = "";
                        da.OBJ_PID = "";
                    }
                    if (Persistent)
                    {
                        data.AddToPersistentList(da, da.PID);
                    }
                }
            }
        }
        #endregion

        #region 采集处理方法
        /// <summary>
        /// 解析数据
        /// </summary>
        /// <param name="data"></param>
        private void AnalyzeData(DAObject data)
        {
            if (_AnalyzerList == null)//如果解析类列表未加载,则执行加载
            {
                LoadAnalyzer();
            }
            IDataAnalyzer analyzer = null;
            if (!string.IsNullOrWhiteSpace(data.DAI.ANALYZE_CODE) && _AnalyzerList.ContainsKey(data.DAI.ANALYZE_CODE)) //检查采集数据的解析编码是否存在于解析类列表中
            {
                analyzer = CreateInstance<IDataAnalyzer>(_AnalyzerList[data.DAI.ANALYZE_CODE].ASSEMBLYNAME, _AnalyzerList[data.DAI.ANALYZE_CODE].CLASSNAME);
            }
            else // 不存在则执行默认解析方法
            {
                analyzer = new DataAnalyzers.DefaultAnalyzer();
            }
            analyzer.Analyze(data);
        }
        /// <summary>
        /// 校验采集数据
        /// </summary>
        /// <param name="data"></param>
        private ValidateResult ValidateData(DAObject data)
        {
            if (_ValidatorList == null)//如果解析类列表未加载,则执行加载
            {
                LoadValidator();
            }
            //获取采集点校验配置
            DAIValidationDAL dal = new DAIValidationDAL();
            var daivalidations = dal.GetList(data.DAI.PID);
            foreach (var validator in _ValidatorList) //遍历校验类
            {
                var daioption = daivalidations.FirstOrDefault(p => p.VALIDATION_CODE == validator.VALIDATOR_CODE);
                if (string.Equals("1", validator.REQUIRED) || daioption != null) //如果校验类为必选项 或 采集点配置此校验
                {
                    if (daioption == null || !string.Equals(daioption.DISABLE, "1"))
                    {
                        IDataValidator datavalidator;
                        datavalidator = CreateInstance<IDataValidator>(validator.ASSEMBLYNAME, validator.CLASSNAME);
                        var result = datavalidator.Validate(data, daioption);
                        if (!result.Passed)//校验未通过
                        {
                            return new ValidateResult(false,
                                string.Format("采集数据校验未通过,{0}:{1}", validator.VALIDATOR_NAME, result.Message));
                        }
                    }
                }
            }
            return new ValidateResult(true, "");
        }
        /// <summary>
        /// 检查工序状态
        /// </summary>
        /// <param name="data"></param>
        private void CheckState(DAObject data,DAResult result)
        {
            if (!string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.PROCESS_CODE))
            {
                result.ProcessCode = data.WorkLocState.CurrentState.PROCESS_CODE;
            }
            //查找当前状态下未赋值的采集点数量
            var novalue_count = data.WorkLocState.DataCache.Count(p => p.STATE_CODE == data.WorkLocState.CurrentState.STATE_CODE //采集点采集状态为当前工序状态
                                                                    && string.IsNullOrWhiteSpace(p.DA_VALUE) //采集点采集值不为空
                                                                    && !string.Equals(p.DA_MODE, "2") //过滤掉可省略的采集点
                                                                    && !string.Equals(p.DA_MODE, "5") //过滤掉可省略的采集点
                                                                    && (data.ReadSignal || !string.Equals(p.DA_CODE, "PLC_PARM"))); //如果当前设备设置为不读信号则过滤掉从当前设备采集的数据
            if (novalue_count == 0) //当前工序状态下得采集点采集完成
            {
                if (!string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.MATERIAL_CODE))
                {
                    var emptyDa = (from dai in data.WorkLocState.DataCache
                                   where dai.STATE_CODE == data.WorkLocState.CurrentState.STATE_CODE //采集点采集状态为当前工序状态 
                                   && string.IsNullOrWhiteSpace(dai.DA_VALUE) //采集值为空
                                   && (string.Equals(dai.DA_MODE, "2") //采集模式不是可忽略的
                                       || string.Equals(dai.DA_MODE, "5")) //采集模式不是可忽略的
                                   orderby dai.DA_SEQ descending
                                   select dai).ToList();
                    if (emptyDa.Count > 0)
                    {
                        PbomDAL dal = new PbomDAL();
                        MD.Entity.View.BomLocation bomloc=null;
                        var bomlocates = dal.LocateBomByUpMaterial(data.WorkLocState.CurrentState.MATERIAL_CODE);
                        if (bomlocates.Count > 0)
                        {
                            bomloc = bomlocates[0];
                        }
                        if (bomloc != null)
                        {
                            var bomitems = dal.GetBomItemsByLocateWithType(bomloc); //查找组成物料列表
                            foreach (var da in emptyDa)
                            {
                                if (bomitems.Exists(p => p.MATERIAL_TYPE_CODE == da.MATERIAL_TYPE || p.UP_MATERIAL_TYPE_CODE == da.MATERIAL_TYPE))
                                {
                                    return;
                                }
                            }
                        }
                    }
                }

                result.StateChanged = true;
                foreach (var action in data.WorkLocState.CurrentState.EXIT_ACTION.Split(';'))//执行退出状态动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                    if (!string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.PROCESS_CODE))
                    {
                        result.ProcessCode = data.WorkLocState.CurrentState.PROCESS_CODE;
                    }
                }
                SetToNextState(data);
                foreach (var action in data.WorkLocState.CurrentState.ENTRY_ACTION.Split(';'))//执行进入状态动作
                {
                    ExecuteAction(action, data);
                    if (!string.IsNullOrWhiteSpace(action))
                        result.Actions.Add(action);
                    if (!string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.PROCESS_CODE))
                    {
                        result.ProcessCode = data.WorkLocState.CurrentState.PROCESS_CODE;
                    }
                }
                
                CheckState(data, result);//递归调用
            }
        }

        /// <summary>
        /// 设置工序到下一个状态
        /// </summary>
        /// <param name="data"></param>
        private void SetToNextState(DAObject data)
        {
            WorkCellRunStateDAL dal = new WorkCellRunStateDAL();
            var state = dal.GetNextState(data.WorkLocState.WORKCELL_CODE, data.WorkLocState.CurrentState.STATE_SEQ);
            if (state == null) //如果状态为空则获取第一个状态
            {
                state = dal.GetNextState(data.WorkLocState.WORKCELL_CODE, 0);
            }
            //更新工序状态
            data.WorkLocState.CurrentState.UPDATEDATE = DateTime.Now;
            data.WorkLocState.CurrentState.ENTRY_ACTION = state.ENTRY_ACTION;
            data.WorkLocState.CurrentState.EXIT_ACTION = state.EXIT_ACTION;
            data.WorkLocState.CurrentState.STATE_SEQ = state.STATE_SEQ;
            data.WorkLocState.CurrentState.STATE_CODE = state.STATE_CODE;
            data.WorkLocState.CurrentState.STATE_NAME = state.STATE_NAME;

            data.AddToPersistentList(data.WorkLocState.CurrentState,data.WorkLocState.CurrentState.PID);
            //dal.Update(data.WorkLocState.CurrentState, data.DataSession);
        }

        /// <summary>
        /// 设置工序到第一个状态
        /// </summary>
        /// <param name="data"></param>
        private void SetToFirstState(DAObject data)
        {
            WorkCellRunStateDAL dal = new WorkCellRunStateDAL();
            var state = dal.GetNextState(data.WorkLocState.WORKCELL_CODE, 0);
            //更新工序状态
            data.WorkLocState.CurrentState.UPDATEDATE = DateTime.Now;
            data.WorkLocState.CurrentState.ENTRY_ACTION = state.ENTRY_ACTION;
            data.WorkLocState.CurrentState.EXIT_ACTION = state.EXIT_ACTION;
            data.WorkLocState.CurrentState.STATE_SEQ = state.STATE_SEQ;
            data.WorkLocState.CurrentState.STATE_CODE = state.STATE_CODE;
            data.WorkLocState.CurrentState.STATE_NAME = state.STATE_NAME;

            data.AddToPersistentList(data.WorkLocState.CurrentState, data.WorkLocState.CurrentState.PID);
            //dal.Update(data.WorkLocState.CurrentState, data.DataSession);
        }
        /// <summary>
        /// 执行状态动作
        /// </summary>
        /// <param name="Action"></param>
        private void ExecuteAction(string action,DAObject data)
        {
            
            if (_StateActionList == null)
            {
                LoadStateAction();
            }
            if (string.IsNullOrWhiteSpace(action))
            {
                return;
            }
            if (_StateActionList.ContainsKey(action))
            {
                var act = CreateInstance<IStateAction>(_StateActionList[action].ASSEMBLYNAME, _StateActionList[action].CLASSNAME);
                act.Execute(data);
            }
            
        }
        /// <summary>
        /// 设置数据采集缓存
        /// </summary>
        /// <param name="data"></param>
        private void SetDACache(DAObject data)
        {
            //DAICacheDAL dal = new DAICacheDAL();
            var daicache = data.WorkLocState.DataCache.FirstOrDefault(p => p.DA_CODE == data.DAI.DA_CODE);
            daicache.DA_VALUE = data.AnalyzedValue;
            daicache.OBJ_PID = data.ObjectPID;
            daicache.MATERIAL_CODE = data.MaterialCode;
            daicache.DA_MODE = data.DAI.DA_MODE;
            daicache.DA_SEQ = data.DAI.DA_SEQ;
            daicache.DA_STATE = data.DAI.DA_STATUS;
            daicache.DATA_TYPE = data.DAI.DATA_TYPE;
            daicache.ISPROCESSCODE = data.DAI.ISPROCESSCODE;
            daicache.MATERIAL_TYPE = data.DAI.MATERIAL_TYPE;
            daicache.PIVOTAL = data.DAI.PIVOTAL;
            daicache.STATE_CODE = data.DAI.STATE_CODE;
            daicache.SAVED = daicache.SAVED.Replace(data.MouldCode, "");
            daicache.MOULD_CODE = data.MouldCode;
            data.AddToPersistentList(daicache, daicache.PID);
            //dal.Update(daicache, data.DataSession);
        }
        #endregion

        #region 静态方法
        /// <summary>
        /// 加载解析类
        /// </summary>
        private static void LoadAnalyzer()
        {
            //lock (_AnalyzerList)
            //{
                AnalyzerDAL dal = new AnalyzerDAL();
                var list = dal.GetList();
                if (_AnalyzerList == null)
                {
                    _AnalyzerList = new Dictionary<string, Analyzer>();
                }
                else
                {
                    if (_AnalyzerList.Count == list.Count)
                    {
                        return;
                    }
                }
                _AnalyzerList.Clear();
                foreach (var analyzer in list)
                {
                    _AnalyzerList.Add(analyzer.ANALYZER_CODE, analyzer);
                }
            //}
        }
        /// <summary>
        /// 加载状态动作
        /// </summary>
        private static void LoadStateAction()
        {
            //lock (_StateActionList)
            //{
                StateActionDAL dal = new StateActionDAL();
                var list = dal.GetServerActionList();
                if (_StateActionList == null)
                {
                    _StateActionList = new Dictionary<string, StateAction>();
                }
                else
                {
                    if (_StateActionList.Count == list.Count)
                    {
                        return;
                    }
                }
                _StateActionList.Clear();
                foreach (var action in list)
                {
                    _StateActionList.Add(action.ACTION_CODE, action);
                }
            //}
        }
        /// <summary>
        /// 加载校验类
        /// </summary>
        private static void LoadValidator()
        {
            //lock (_ValidatorList)
            //{
                ValidatorDAL dal = new ValidatorDAL();
                var list = dal.GetList();
                if (_ValidatorList == null)
                {
                    _ValidatorList = new List<Validator>();
                }
                else
                {
                    if (_ValidatorList.Count == list.Count)
                    {
                        return;
                    }
                }
                _ValidatorList.Clear();
                foreach (var validator in list)
                {
                    _ValidatorList.Add(validator);
                }
            //}
        }
        /// <summary>
        /// 根据配置信息创建所对应的接口
        /// </summary>
        /// <typeparam name="T">要创建的接口</typeparam>
        /// <param name="AssemblyName">程序集</param>
        /// <param name="ClassPath">实现类全路径</param>
        /// <returns>创建的接口</returns>
        public static T CreateInstance<T>(String AssemblyName, String ClassPath)
        {
            Assembly _asse;
            Type _type;
            Object _obj;
            T _mc;
            _asse = Assembly.Load(AssemblyName);
            _type = _asse.GetType(ClassPath);
            _obj = System.Activator.CreateInstance(_type);
            _mc = (T)_obj;
            return _mc;
        }
        #endregion
    }
}