using HighWayIot.Log4net;
using HighWayIot.Plc;
using HighWayIot.Plc.PlcHelper;
using HighWayIot.Repository.domain;
using HighWayIot.Repository.service;
using Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Schema;
using static Org.BouncyCastle.Math.EC.ECCurve;
using Timer = System.Threading.Timer;

namespace HighWayIot.Winform.Business
{
    /// <summary>
    /// 排程信号业务类
    /// </summary>
    public class RecipeSendBusiness
    {
        private Timer GetSchedulingTimer;

        private RecipeSignal recipeSignal = new RecipeSignal();

        private ZxSchedulingService zxSchedulingService = ZxSchedulingService.Instance;

        private ZxRecipeParaService zxRecipeParaService = ZxRecipeParaService.Instance;

        private ZxRecipePositionParaService zxRecipePositionParaService = ZxRecipePositionParaService.Instance;

        private RecipeParaHelper recipeParaHelper = new RecipeParaHelper();

        public static bool RecipeSendMode = false;

        public static string NowRecipeCode = string.Empty;

        public static string NowDeviceNo = string.Empty;

        public RecipeSendBusiness()
        {
            GetSchedulingTimer = new Timer(new System.Threading.TimerCallback(ReadSignal), null, 0, 1500);
        }
        /// <summary>
        /// 重复读取
        /// </summary>
        /// <param name="o"></param>
        public void ReadSignal(object o)
        {
            //读取是True的点位

            Dictionary<int, bool> a = recipeSignal.ReadSchedulingSignal();

            if (a == null)
            {
                return;
            }

            int destinationVulcanizationNo;
            var ares = a.Where(x => x.Value == true).ToList();
            if (ares.Count == 1)
            {
                destinationVulcanizationNo = ares[0].Key;
            }
            else
            {
                if (ares.Count > 1)
                {
                    LogHelper.Instance.Error($"排程信号True值不唯一 {string.Join(", ", ares.Select(x => x.Key).ToList())}");
                }
                return;
            }
            var schedulingInfo = zxSchedulingService.GetSchedulingInfo();

            if (RecipeSendMode) //通过MES下配方
            {
                //读同步数据库，找到等于0的
                List<ZxMesPlanTransferEntity> transferEntity = ZxMesPlanTransferService.Instance.GetRecipeInfos(x => x.RequestFlag == false).ToList();
                if (transferEntity.Count > 1)
                {
                    LogHelper.Instance.Error($"标识同步数据不唯一，请检查是否有多选情况发生，当前数量：{transferEntity.Count}");
                    return;
                }
                if (transferEntity.Count == 0)
                {
                    LogHelper.Instance.Error("配方下发请求不存在，等待MES同步");
                    return;
                }

                //同步配方
                ZxMesPlanTransferEntity newRecipes = transferEntity.First();
                SyncRecipe(newRecipes);
                ZxMesPlanTransferService.Instance.SetFlagTrue();

                //同步到对应硫化排程的界面
                ZxSchedulingEntity schedulingEntity;
                if ((destinationVulcanizationNo + 1) <= 62) //上模
                {
                    schedulingEntity = schedulingInfo.Single(x => x.Id == destinationVulcanizationNo + 1);
                    schedulingEntity.RecipeName2 = newRecipes.RecipeName;
                    schedulingEntity.RecipeCode2 = newRecipes.RecipeCode;
                }
                else //下模
                {
                    schedulingEntity = schedulingInfo.Single(x => x.Id == destinationVulcanizationNo + 1 - 62);
                    schedulingEntity.RecipeName1 = newRecipes.RecipeName;
                    schedulingEntity.RecipeCode1 = newRecipes.RecipeCode;
                }
                ZxSchedulingService.Instance.UpdateSchedulingInfo(schedulingEntity);
            }
            string recipeNo;
            ZxRecipeParaEntity recipeParaInfo;
            List<ZxRecipePositionParaEntity> zxRecipePositionParaEntities;
            if ((destinationVulcanizationNo + 1) <= 62) //上模
            {
                recipeNo = schedulingInfo.Single(x => x.Id == destinationVulcanizationNo + 1).RecipeCode1;
                recipeParaInfo = zxRecipeParaService.GetRecipeParaInfoByRecipeCode(recipeNo).FirstOrDefault();
                zxRecipePositionParaEntities = zxRecipePositionParaService.GetRecipePositionParaInfos(x => x.RecipeCode == recipeNo);
                if (recipeParaInfo == null)
                {
                    LogHelper.Instance.Error("配方信息获取失败，请检查所选机台是否配置了相应配方");
                    return;
                }
                if (recipeParaHelper.UploadToPLC(recipeParaInfo, zxRecipePositionParaEntities))
                {
                    //PlcConnect.PlcWrite2($"B{(destinationVulcanizationNo + 0x901).ToString("X")}", false, DataTypeEnum.Bool);
                    int deviceNo = schedulingInfo.Single(x => x.Id == destinationVulcanizationNo + 1).DeviceNo ?? 0;
                    //MonitorInsert(recipeNo, $"{deviceNo}上模");
                    LogHelper.Instance.Info($"配方上传成功,配方号：{recipeNo},模具号：{deviceNo}上模");
                    NowRecipeCode = recipeNo;
                    NowDeviceNo = deviceNo + "-2";
                }
                else
                {
                    LogHelper.Instance.Error("配方上传失败，检查PLC连接");
                    return;
                }
            }
            else //下模
            {
                recipeNo = schedulingInfo.Single(x => x.Id == destinationVulcanizationNo + 1 - 62).RecipeCode2;
                recipeParaInfo = zxRecipeParaService.GetRecipeParaInfoByRecipeCode(recipeNo).FirstOrDefault();
                zxRecipePositionParaEntities = zxRecipePositionParaService.GetRecipePositionParaInfos(x => x.RecipeCode == recipeNo);
                if (recipeParaInfo == null)
                {
                    LogHelper.Instance.Error("配方信息获取失败，请检查所选机台是否配置了相应配方");
                    return;
                }
                if (recipeParaHelper.UploadToPLC(recipeParaInfo, zxRecipePositionParaEntities))
                {
                    //PlcConnect.PlcWrite2($"B{(destinationVulcanizationNo - 62 + 0x941).ToString("X")}", false, DataTypeEnum.Bool);
                    int deviceNo = schedulingInfo.Single(x => x.Id == destinationVulcanizationNo + 1 - 62).DeviceNo ?? 0;
                    //MonitorInsert(recipeNo, $"{deviceNo}下模");
                    LogHelper.Instance.Info($"配方上传成功,配方号：{recipeNo},模具号：{deviceNo}下模");
                    NowRecipeCode = recipeNo;
                    NowDeviceNo = deviceNo + "-1";
                }
                else
                {
                    LogHelper.Instance.Error("配方上传失败，检查PLC连接");
                    return;
                }
            }
        }

        /// <summary>
        /// 配方同步方法
        /// </summary>
        public void SyncRecipe(ZxMesPlanTransferEntity newRecipe)
        {
            if (newRecipe == null)
            {
                return;
            }
            //同步到配方（配方和称量，如果是新的加字段）
            List<ZxRecipeEntity> RecipeLists = ZxRecipeService.Instance.GetRecipeInfos();
            var nowEneity = RecipeLists.Where(x => x.RecipeCode == newRecipe.RecipeCode && x.IsDeleted == false).FirstOrDefault();
            if (nowEneity != null)   //有就更新 只更新配方和称量信息
            {
                //同步配方
                nowEneity.RecipeSpecCode = newRecipe.SpecCode;
                nowEneity.RecipeSpecName = newRecipe.SpecName;
                nowEneity.SizeKind = newRecipe.RimInch;
                nowEneity.FixedWidth = newRecipe.FixRubWidth;
                if (!ZxRecipeService.Instance.UpdateRecipeInfo(nowEneity))
                {
                    return;
                }

                //同步称量信息
                List<ZxWeightEntity> zxWeightEntities = ZxWeightService.Instance.GetWeightInfos(nowEneity.RecipeCode);
                for (int i = 1; i <= 3; i++)
                {
                    string typeName = string.Empty;
                    switch (i)
                    {
                        case 1:
                            typeName = "基部胶";
                            break;
                        case 2:
                            typeName = "中层胶";
                            break;
                        case 3:
                            typeName = "胎面胶";
                            break;
                        default:
                            break;
                    }
                    string MaterialName = Convert.ToString(newRecipe.GetType().GetProperty($"MaterialName{i}").GetValue(newRecipe));
                    if (!string.IsNullOrEmpty(MaterialName))
                    {
                        ZxWeightEntity weight = zxWeightEntities.FirstOrDefault(x => x.MaterialCode == MaterialName);
                        if (weight != null) //原来就有
                        {
                            weight.SetThickness = Convert.ToDecimal(newRecipe.GetType().GetProperty($"MaterialThickness{i}").GetValue(newRecipe)); //(decimal)newRecipe.MaterialThickness1;
                            weight.SetWidth = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}").GetValue(newRecipe)); //newRecipe.MaterialWidth1;
                            weight.SetWidth2 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}2").GetValue(newRecipe)); //newRecipe.MaterialWidth12;
                            weight.SetWidth3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}3").GetValue(newRecipe)); //newRecipe.MaterialWidth13;
                            weight.SetLayer = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}").GetValue(newRecipe)); //newRecipe.MaterialLayers1;
                            weight.SetLayer2 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}2").GetValue(newRecipe)); //newRecipe.MaterialLayers12;
                            weight.SetLayer3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}3").GetValue(newRecipe)); //newRecipe.MaterialLayers13;
                            ZxWeightService.Instance.UpdateWeightInfo(weight);
                        }
                        else //原来没有就添加
                        {
                            ZxWeightService.Instance.InsertWeightInfo(new ZxWeightEntity()
                            {
                                RecipeCode = newRecipe.RecipeCode,
                                MaterialCode = MaterialName,
                                MaterialName = MaterialName + typeName,
                                MaterialType = typeName,
                                SetThickness = Convert.ToDecimal(newRecipe.GetType().GetProperty($"MaterialThickness{i}").GetValue(newRecipe)),
                                SetWidth = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}").GetValue(newRecipe)),
                                SetWidth2 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}2").GetValue(newRecipe)),
                                SetWidth3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}3").GetValue(newRecipe)),
                                SetLayer = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}").GetValue(newRecipe)),
                                SetLayer2 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}2").GetValue(newRecipe)),
                                SetLayer3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}3").GetValue(newRecipe)),
                                SetError = 1,
                                IsUse = true,
                                IsDeleted = false,
                            });
                        }
                    }
                }
            }
            else  //没有就插入 全部同步
            {
                //同步配方
                ZxRecipeEntity entity = new ZxRecipeEntity()
                {
                    RecipeName = newRecipe.RecipeName,
                    RecipeCode = newRecipe.RecipeCode,
                    RecipeSpecCode = newRecipe.SpecCode,
                    RecipeSpecName = newRecipe.SpecName,
                    SizeKind = newRecipe.RimInch,
                    FixedWidth = newRecipe.FixRubWidth,
                    IsUse = true,
                    IsDeleted = false,
                };
                ZxRecipeService.Instance.InsertRecipeInfo(entity);

                //同步称量信息
                List<ZxWeightEntity> zxWeightEntities = ZxWeightService.Instance.GetWeightInfos(nowEneity.RecipeCode);
                for (int i = 1; i <= 3; i++)
                {
                    string typeName = string.Empty;
                    switch (i)
                    {
                        case 1:
                            typeName = "基部胶";
                            break;
                        case 2:
                            typeName = "中层胶";
                            break;
                        case 3:
                            typeName = "胎面胶";
                            break;
                        default:
                            break;
                    }
                    string MaterialName = Convert.ToString(newRecipe.GetType().GetProperty($"MaterialName{i}").GetValue(newRecipe));
                    if (!string.IsNullOrEmpty(MaterialName))
                    {
                        ZxWeightEntity weight = zxWeightEntities.FirstOrDefault(x => x.MaterialCode == MaterialName);
                        if (weight != null) //原来就有
                        {
                            weight.SetThickness = Convert.ToDecimal(newRecipe.GetType().GetProperty($"MaterialThickness{i}").GetValue(newRecipe)); //(decimal)newRecipe.MaterialThickness1;
                            weight.SetWidth = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}").GetValue(newRecipe)); //newRecipe.MaterialWidth1;
                            weight.SetWidth2 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}2").GetValue(newRecipe)); //newRecipe.MaterialWidth12;
                            weight.SetWidth3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}3").GetValue(newRecipe)); //newRecipe.MaterialWidth13;
                            weight.SetLayer = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}").GetValue(newRecipe)); //newRecipe.MaterialLayers1;
                            weight.SetLayer2 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}2").GetValue(newRecipe)); //newRecipe.MaterialLayers12;
                            weight.SetLayer3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}3").GetValue(newRecipe)); //newRecipe.MaterialLayers13;
                            ZxWeightService.Instance.UpdateWeightInfo(weight);
                        }
                        else //原来没有就添加
                        {
                            ZxWeightService.Instance.InsertWeightInfo(new ZxWeightEntity()
                            {
                                RecipeCode = newRecipe.RecipeCode,
                                MaterialCode = MaterialName,
                                MaterialName = MaterialName + typeName,
                                MaterialType = typeName,
                                SetThickness = Convert.ToDecimal(newRecipe.GetType().GetProperty($"MaterialThickness{i}").GetValue(newRecipe)),
                                SetWidth = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}").GetValue(newRecipe)),
                                SetWidth2 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}2").GetValue(newRecipe)),
                                SetWidth3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}3").GetValue(newRecipe)),
                                SetLayer = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}").GetValue(newRecipe)),
                                SetLayer2 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}2").GetValue(newRecipe)),
                                SetLayer3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}3").GetValue(newRecipe)),
                                SetError = 1,
                                IsUse = true,
                                IsDeleted = false,
                            });
                        }
                    }
                }

                //同步公共参数
                ZxRecipeParaEntity recipeParaEntity = new ZxRecipeParaEntity();
                recipeParaEntity.RimInch = newRecipe.RimInch;
                recipeParaEntity.LightWidth = newRecipe.FixRubWidth;
                recipeParaEntity.SlowDistance = 0;
                recipeParaEntity.StopDistance = 0;
                recipeParaEntity.TireWeight = newRecipe.TireWeight;
                recipeParaEntity.SpecCode = newRecipe.SpecCode;
                recipeParaEntity.SpecName = newRecipe.SpecName;
                recipeParaEntity.RecipeCode = newRecipe.RecipeCode;

                //自动工位选择
                zxWeightEntities.Clear();
                zxWeightEntities = ZxWeightService.Instance.GetWeightInfos(nowEneity.RecipeCode);
                List<ZxOpenMixMaterialEntity> openMixConfig = ZxOpenMixMaterialService.Instance.GetInfos();
                foreach (ZxWeightEntity weightEntity in zxWeightEntities)
                {
                    var config = openMixConfig.Where(x => x.MaterialName == weightEntity.MaterialName).FirstOrDefault();
                    if (config == null)
                    {
                        continue;
                    }
                    var prop = recipeParaEntity.GetType().GetProperty($"S{config.StationNo + 1}");
                    if (prop != null)
                    {
                        prop.SetValue(recipeParaEntity, true);
                    }
                    //自动包边选择
                    if (!(weightEntity.SetLayer2 == 0
                        || weightEntity.SetLayer2 == null
                        || weightEntity.SetWidth2 == null
                        || weightEntity.SetWidth2 == 0))
                    {
                        var propp = recipeParaEntity.GetType().GetProperty($"B{config.StationNo - 1}");
                        if (propp != null)
                        {
                            propp.SetValue(recipeParaEntity, true);
                        }
                    }
                    if (!(weightEntity.SetLayer3 == 0
                        || weightEntity.SetLayer3 == null
                        || weightEntity.SetWidth3 == null
                        || weightEntity.SetWidth3 == 0))
                    {
                        var propp = recipeParaEntity.GetType().GetProperty($"B{config.StationNo + 4}");
                        if (propp != null)
                        {
                            propp.SetValue(recipeParaEntity, true);
                        }
                    }
                    //设置胎体重量
                    if (weightEntity.MaterialType == "胎面胶")
                    {
                        recipeParaEntity.TireWeight = Convert.ToSingle(weightEntity.SetWeight);
                        switch (config.StationNo)
                        {
                            case 3:
                                recipeParaEntity.S7 = true;
                                break;
                            case 4:
                                recipeParaEntity.S8 = true;
                                break;
                            case 5:
                                recipeParaEntity.S9 = true;
                                break;
                            default:
                                break;
                        }
                    }
                }
                ZxRecipeParaEntity nowRecipeParaEntity = ZxRecipeParaService.Instance.GetRecipeParaInfoByRecipeCode(nowEneity.RecipeCode).FirstOrDefault();

                if (nowRecipeParaEntity != null) //如果存在就更改
                {
                    recipeParaEntity.Id = nowRecipeParaEntity.Id;
                    ZxRecipeParaService.Instance.UpdateRecipeParaInfo(recipeParaEntity);
                }
                else
                {
                    ZxRecipeParaService.Instance.InsertRecipeParaInfo(recipeParaEntity);
                }

                //同步工位参数
                ZxRecipePositionParaService.Instance.DeleteRecipePositionParaInfoByRecipeCode(newRecipe.RecipeCode); //删除可能存在的脏数据
                for (int i = 1; i <= 3; i++)
                {
                    string MaterialName = Convert.ToString(newRecipe.GetType().GetProperty($"MaterialName{i}").GetValue(newRecipe));
                    if (string.IsNullOrEmpty(MaterialName))
                    {
                        continue;
                    }

                    var config = openMixConfig.Where(x => x.MaterialName.Contains(MaterialName)).FirstOrDefault();
                    if (config == null)
                    {
                        continue;
                    }
                    ZxRecipePositionParaEntity positionEntity = new ZxRecipePositionParaEntity()
                    {
                        RecipeCode = newRecipe.RecipeCode,
                        Position = config.StationNo,
                        E1 = 15,
                        E2 = 52,
                        E5 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}").GetValue(newRecipe)) * 10,
                        E9 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}").GetValue(newRecipe)),
                        E6 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}2").GetValue(newRecipe)) * 10,
                        E7 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}2").GetValue(newRecipe)),
                        E3 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialLayers{i}3").GetValue(newRecipe)) * 10,
                        E4 = Convert.ToInt32(newRecipe.GetType().GetProperty($"MaterialWidth{i}3").GetValue(newRecipe)),
                        E10 = 800,
                        E8 = 300
                    };

                    ZxRecipePositionParaService.Instance.InsertRecipePositionParaInfo(positionEntity);
                }

            }

        }
    }
}
