using iWareSda.Common;
using iWareModel;
using System;
using System.Collections.Generic;
using System.Threading;
using iWareCommon.Utils;
using iWareCommon.Common.Globle;
using iWareCommon;
using iWareSda.Model;
namespace iWareSda
{
    /// 
    /// 每台堆垛机的实时信息
    /// 
    public class SrmEntity : IDevice
    {
        public SrmEntity()
        {
            this.View = new SrmView();
        }
        #region OPC相关
        /// 
        /// 写的DB块
        /// 
        public SrmDBForWrite DBBlockForWrite { get; set; }
        /// 
        /// 读的DB块
        /// 
        public SrmDBForRead DBBlockForRead { get; set; }
        /// 
        /// 读取PLC实例
        /// 
        public PLCService plcService { get; set; }
        /// 
        /// 视图对象
        /// 
        public SrmView View { get; set; }
        #endregion
        /// 
        /// 初始化数据
        /// 
        public void InitData()
        {
        }
        public SrmEntity(string srmName, int deviceId, SrmDBForWrite _dbBlockForWrite, SrmDBForRead _dbBlockForRead, PLCService _plcService)
        {
            this.View = new SrmView();
            this.View.DeviceName = srmName;
            this.View.DeviceId = deviceId;
            plcService = _plcService;
            DBBlockForWrite = _dbBlockForWrite;
            DBBlockForRead = _dbBlockForRead;
        }
        #region 个性化方法
        /// 
        /// 是否允许给堆垛机发送新任务
        /// 
        /// 
        /// 
        public bool IsAllowSendNewTaskToSrm()
        {
            Thread.Sleep(2000);//等待一秒钟 【EditBy shaocx,2022-03-26】
            if (this.View.ModeName == "自动" && this.View.R_AlarmCode == 0 && (this.View.R_WarningDBList == null || this.View.R_WarningDBList.Count == 0)
                && this.View.StateName == "空闲")
            {
                return true;
            }
            return false;
        }
        /// 
        /// 重新格式化处理站点号
        /// 
        /// 
        /// 
        public void ReSubStringPlace(ref string sourcePlace, ref string toPlace)
        {//1-01-03-04 转换为 01-03-04
            sourcePlace = sourcePlace.Substring(2, sourcePlace.Length - 2);
            toPlace = toPlace.Substring(2, toPlace.Length - 2);
        }
        /// 
        /// 给堆垛机发送指令
        /// 
        /// 堆垛机设备号
        /// 任务号
        /// 起始位
        /// 目标位
        /// 任务类型
        /// 错误消息
        /// 
        public bool SendTask(ESrmCmd srmCmd, int deviceId, int taskId, string sourcePlace, string toPlace, out string msg)
        {
            try
            {
                msg = "";
                if (!CanDoTask(deviceId, out msg))
                {
                    return false;
                }
                //Z 排 X 列 Y层
                //01-02-03
                int sourceZ = 0, sourceX = 0, sourceY = 0;
                if (srmCmd == ESrmCmd.库内搬运 || srmCmd == ESrmCmd.入库 || srmCmd == ESrmCmd.出库)
                {
                    var arr_source = sourcePlace.Split('-');
                    //int sourceZ = int.Parse(sourcePlace.Substring(0, 2));
                    //int sourceX = int.Parse(sourcePlace.Substring(2, 4));
                    //int sourceY = int.Parse(sourcePlace.Substring(3, 2));
                    sourceZ = int.Parse(arr_source[0]);
                    sourceX = int.Parse(arr_source[1]);
                    sourceY = int.Parse(arr_source[2]);
                    ConvertPlaceToSrm(deviceId, ref srmCmd, true, sourcePlace, ref sourceZ, ref sourceX, ref sourceY);
                }
                var arr_to = toPlace.Split('-');
                //int toZ = int.Parse(toPlace.Substring(0, 1));
                //int toX = int.Parse(toPlace.Substring(1, 2));
                //int toY = int.Parse(toPlace.Substring(3, 2));
                int toZ = int.Parse(arr_to[0]);
                int toX = int.Parse(arr_to[1]);
                int toY = int.Parse(arr_to[2]);
                ConvertPlaceToSrm(deviceId, ref srmCmd, false, toPlace, ref toZ, ref toX, ref toY);
                //发送指令
                var ss = this.plcService;
                ////只有一台堆垛机,不需要写
                //var constValue = 1;
                //MessageModel b1 = this.plcService.WriteValuePoint( this.DBBlockForWrite.W_SrmNo, constValue, this.View.W_SrmNo);
                //if (!b1.result)
                //{
                //    msg = string.Format("向堆垛机{0}发送任务{1},写入设备编号" + constValue + "失败,返回结果:" + b1.resMsg, this.View.DeviceName, taskId);
                //    return false;
                //}
                MessageModel b2 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_TaskNo, taskId, this.View.W_TaskNo);
                if (!b2.result)
                {
                    msg = string.Format("向堆垛机{0}发送任务{1},写入任务号" + taskId + "失败,返回结果:" + b2.resMsg, this.View.DeviceName, taskId);
                    return false;
                }
                //MessageModel b60 = this.plcService.WriteValuePoint( this.DBBlockForWrite.W_PalletType, constValue, this.View.W_PalletType);
                //if (!b60.result)
                //{
                //    msg = string.Format("向堆垛机{0}发送任务{1},写入托盘类型" + constValue + "失败,返回结果:" + b60.resMsg, this.View.DeviceName, taskId);
                //    return false;
                //}
                if (srmCmd == ESrmCmd.库内搬运 || srmCmd == ESrmCmd.入库 || srmCmd == ESrmCmd.出库)
                {
                    MessageModel b5 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_SourcePosZ, sourceZ, this.View.W_SourcePosZ);
                    if (!b5.result)
                    {
                        msg = string.Format("向堆垛机{0}发送任务{1},写入sourceZ失败,返回结果:" + b5.resMsg, this.View.DeviceName, taskId);
                        return false;
                    }
                    MessageModel b4 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_SourcePosX, sourceX, this.View.W_SourcePosX);
                    if (!b4.result)
                    {
                        msg = string.Format("向堆垛机{0}发送任务{1},写入sourceX失败,返回结果:" + b4.resMsg, this.View.DeviceName, taskId);
                        return false;
                    }
                    MessageModel b3 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_SourcePosY, sourceY, this.View.W_SourcePosY);
                    if (!b3.result)
                    {
                        msg = string.Format("向堆垛机{0}发送任务{1},写入sourceY失败,返回结果:" + b3.resMsg, this.View.DeviceName, taskId);
                        return false;
                    }
                }
                MessageModel b8 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_DestinationPosZ, toZ, this.View.W_DestinationPosZ);
                if (!b8.result)
                {
                    msg = string.Format("向堆垛机{0}发送任务{1},写入toZ失败,返回结果:" + b8.resMsg, this.View.DeviceName, taskId);
                    return false;
                }
                MessageModel b7 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_DestinationPosX, toX, this.View.W_DestinationPosX);
                if (!b7.result)
                {
                    msg = string.Format("向堆垛机{0}发送任务{1},写入toX失败,返回结果:" + b7.resMsg, this.View.DeviceName, taskId);
                    return false;
                }
                MessageModel b6 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_DestinationPosY, toY, this.View.W_DestinationPosY);
                if (!b6.result)
                {
                    msg = string.Format("向堆垛机{0}发送任务{1},写入toY失败,返回结果:" + b6.resMsg, this.View.DeviceName, taskId);
                    return false;
                }
                short command = (short)srmCmd;
                MessageModel b10 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_Command, command, this.View.W_Command);
                if (!b10.result)
                {
                    msg = string.Format("向堆垛机{0}发送任务{1},写入command失败,返回结果:" + b10.resMsg, this.View.DeviceName, taskId);
                    return false;
                }
                MessageModel b9 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_Stb, 1, this.View.W_Stb);
                if (!b9.result)
                {
                    msg = string.Format("向堆垛机{0}发送任务{1},写入W_Stb失败,返回结果:" + b9.resMsg, this.View.DeviceName, taskId);
                    return false;
                }
                //重置如下状态
                //不需要重置 【EditBy shaocx,2022-04-09】
                //this.plcService.WriteValuePoint( this.DBBlockForWrite.W_EmergencyStop, 0, this.View.W_EmergencyStop);
                //this.plcService.WriteValuePoint( this.DBBlockForWrite.W_CancleAlarm, 0, this.View.W_CancleAlarm);
                //this.plcService.WriteValuePoint( this.DBBlockForWrite.W_TaskFinishConfirm, 0, this.View.W_TaskFinishConfirm);
                //this.plcService.WriteValuePoint( this.DBBlockForWrite.W_Ack, 0, this.View.W_Ack);
                return true;
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                Log4NetHelper.WriteErrorLog(Srm_CacheEntity.curLogType, "发送任务出现异常:" + ex.Message, ex);
                return false;
            }
        }
        /// 
        /// 堆垛机上的站点转换
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        private void ConvertPlaceToSrm(int deviceId, ref ESrmCmd srmCmd, bool isSource, string place, ref int z, ref int x, ref int y)
        {
            if (deviceId == (int)EDevice.四号堆垛机)
            {
                if (place == "02-01-01")
                {//入口
                    x = 801;
                    y = 0;
                    z = 0;
                    if (isSource && srmCmd == ESrmCmd.库内搬运)
                    {//如果是起点是入库口
                        srmCmd = ESrmCmd.入库;
                    }
                }
                else if (place == "01-01-01")
                {//出口
                    x = 901;
                    y = 0;
                    z = 0;
                    if (isSource == false && srmCmd == ESrmCmd.库内搬运)
                    {//如果是目标点是出口
                        srmCmd = ESrmCmd.出库;
                    }
                }
            }
            else
            {
                if (place == "01-01-01")
                {//入口
                    x = 801;
                    y = 0;
                    z = 0;
                    if (isSource && srmCmd == ESrmCmd.库内搬运)
                    {//如果是起点是入库口
                        srmCmd = ESrmCmd.入库;
                    }
                }
                else if (place == "02-01-01")
                {//出口
                    x = 901;
                    y = 0;
                    z = 0;
                    if (isSource == false && srmCmd == ESrmCmd.库内搬运)
                    {//如果是目标点是出口
                        srmCmd = ESrmCmd.出库;
                    }
                }
            }
        }
        /// 
        /// 任务删除
        /// 
        /// 
        /// 
        /// 
        /// 
        public bool SendDelTask(int deviceId, out string msg)
        {
            try
            {
                msg = "";
                if (!CanDeleteTask(deviceId, out msg))
                {
                    return false;
                }
                MessageModel b3 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_Command, (int)ESrmCmd.任务删除, this.View.W_Command);
                if (!(b3.result))
                {
                    msg = string.Format("向堆垛机{0}发送删除任务失败,返回结果:" + b3.resMsg, this.View.DeviceName);
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteErrorLog(Srm_CacheEntity.curLogType, "任务删除出现异常:" + ex.Message, ex);
                throw ex;
            }
        }
        /// 
        /// 堆垛机解警
        /// 
        /// 
        /// 
        public bool ReleaseAlert(out string msg)
        {
            try
            {
                msg = "";
                MessageModel b1 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_CancleAlarm, 1, this.View.W_CancleAlarm);
                if (!(b1.result))
                {
                    msg = string.Format("向堆垛机{0}发送解警指令失败,返回结果:" + b1.resMsg, this.View.DeviceName);
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteErrorLog(Srm_CacheEntity.curLogType, "发送解警指令异常:" + ex.Message, ex);
                throw ex;
            }
        }
        /// 
        /// 堆垛机急停
        /// 
        /// 
        /// 
        public bool SendEStop(out string msg)
        {
            try
            {
                msg = "";
                MessageModel b1 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_EmergencyStop, 1, this.View.W_EmergencyStop);
                if (!(b1.result))
                {
                    msg = string.Format("向堆垛机{0}发送急停指令失败,返回结果:" + b1.resMsg, this.View.DeviceName);
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteErrorLog(Srm_CacheEntity.curLogType, "发送急停指令异常:" + ex.Message, ex);
                throw ex;
            }
        }
        /// 
        /// 堆垛机任务确认
        /// 
        /// 
        /// 
        public bool ConfirmTaskFinish(out string msg)
        {
            try
            {
                msg = "";
                MessageModel b1 = this.plcService.WriteValuePoint(this.DBBlockForWrite.W_TaskFinishConfirm, 1, this.View.W_TaskFinishConfirm);
                if (!(b1.result))
                {
                    msg = string.Format("向堆垛机{0}发送任务确认指令失败,返回结果:" + b1.resMsg, this.View.DeviceName);
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteErrorLog(Srm_CacheEntity.curLogType, "发送任务确认指令异常:" + ex.Message, ex);
                throw ex;
            }
        }
        /// 
        /// 堆垛机继续任务
        /// 
        /// 
        /// 
        public bool ContinueTask(out string msg)
        {
            try
            {
                msg = "";
                //var dbNumber = Srm_CacheEntity.W_DBHeader;
                //FunctionReturnEntity b1 = this.S7.WriteValuePoint( this.DBBlock.con, 1);
                //if (!(b1.result))
                //{
                //    msg = string.Format("向堆垛机{0}发送解警指令失败,返回结果:" + b1.resMsg, this.DeviceName);
                //    return false;
                //}
                return true;
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteErrorLog(Srm_CacheEntity.curLogType, "堆垛机继续任务异常:" + ex.Message, ex);
                throw ex;
            }
        }
        /// 
        /// 是否可以下发任务
        /// 
        /// 
        /// 
        /// 
        public bool CanDoTask(int deviceId, out string msg)
        {
            msg = "";
            //在不在线不需要校验,不在线的话
            if (this.View.R_Mode != 1)
            {
                msg = string.Format("堆垛机{0}非自动模式", this.View.DeviceName);
                return false;
            }
            if (this.View.R_Alarm == 1)
            {
                msg = string.Format("堆垛机{0}报警中", this.View.DeviceName);
                return false;
            }
            if (this.View.R_LiftFull == 1)
            {
                msg = string.Format("堆垛机{0}叉齿有货", this.View.DeviceName);
                return false;
            }
            if (this.View.R_PosZ != 0)
            {
                msg = string.Format("堆垛机{0}叉齿不在原点", this.View.DeviceName);
                return false;
            }
            //*/
            if (this.View.R_State != (int)ESrmState.空闲)
            {
                msg = string.Format("堆垛机{0}非空闲", this.View.DeviceName);
                return false;
            }
            return true;
        }
        /// 
        /// 是否可以删除任务
        /// 
        /// 
        /// 
        /// 
        private bool CanDeleteTask(int deviceId, out string msg)
        {
            msg = "";
            //在不在线不需要校验,不在线的话
            if (this.View.R_Mode != 1)
            {
                msg = string.Format("堆垛机{0}非自动模式", this.View.DeviceName);
                return false;
            }
            return true;
        }
        #endregion
        public void SetPropertyValueForRead()
        {
            var r_dbBlock = this.DBBlockForRead;
            SdaHelper.SetPropertyValueForDB(r_dbBlock, this.View, this.plcService, "");
        }
        public void SetPropertyValueForWrite()
        {
            var w_dbBlock = this.DBBlockForWrite;
            SdaHelper.SetPropertyValueForDB(w_dbBlock, this.View, this.plcService, "");
        }
        /// 
        /// 是否有心跳
        /// 
        /// 
        public bool IsHaveHeatBeat()
        {
            try
            {
                var r_dbBlock = this.DBBlockForRead;
                short value = Convert.ToInt16(this.plcService.ReadValuePoint(r_dbBlock.R_HandShake, typeof(short)));
                //约定 等待2秒
                Thread.Sleep(2000);
                short value_next = Convert.ToInt16(this.plcService.ReadValuePoint(r_dbBlock.R_HandShake, typeof(short)));
                if (value == value_next)
                {//没有心跳
                    return false;
                }
                else
                {//有心跳
                    return true;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// 
        /// 组合 起始点
        /// 
        /// 
        public string GetSrmSourcePlace()
        {
            if (this.View.W_SourcePosZ != 0)
            {
                return this.View.W_SourcePosZ.ToString("00") + "-" + this.View.W_SourcePosX.ToString("00") + "-" + this.View.W_SourcePosY.ToString("00");
            }
            return GetPlaceForInOutStation(this.View.W_SourcePosX);
        }
        /// 
        /// 组合 目标点
        /// 
        /// 
        public string GetSrmToPlace()
        {
            if (this.View.W_DestinationPosZ != 0)
            {
                return this.View.W_DestinationPosZ.ToString("00") + "-" + this.View.W_DestinationPosX.ToString("00") + "-" + this.View.W_DestinationPosY.ToString("00");
            }
            return GetPlaceForInOutStation(this.View.W_DestinationPosX);
        }
        /// 
        /// 单独获取出入口站点名
        /// 
        /// 
        /// 
        private string GetPlaceForInOutStation(short xVaue)
        {
            if (xVaue == 801)
            {
                if (this.View.DeviceId == (int)EDevice.四号堆垛机)
                {
                    return "02-01-01";
                }
                else
                {
                    return "01-01-01";
                }
            }
            else if (xVaue == 901)
            {
                if (this.View.DeviceId == (int)EDevice.四号堆垛机)
                {
                    return "01-01-01";
                }
                else
                {
                    return "02-01-01";
                }
            }
            return "";
        }
        #region 获取当前报警信息
        /// 
        /// 获取当前报警信息
        /// 
        /// 
        public List GetAlertDatas()
        {
            List db_warningList = new List();
            try
            {
                string _dbValue;
                var isHasAlert = false;
                IDictionary srmAlertDict = new Dictionary();
                srmAlertDict = WareSdaStruct.SrmAlertDict;
                foreach (var item in srmAlertDict)
                {
                    _dbValue = item.Key;
                    isHasAlert = Convert.ToBoolean(this.plcService.ReadValuePoint(Srm_CacheEntity.R_DBHeader_Alert, item.Key, typeof(bool)));
                    if (isHasAlert)
                    {
                        db_warningList.Add(new DeviceWarningInfo()
                        {
                            Address = item.Key,
                            Code = item.Key,
                            Context = item.Value.Trim()
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return db_warningList;
        }
        #endregion
    }
}