using Khd.Core.Domain.Dto.webapi;
using Khd.Core.Domain.Models;
using Khd.Core.EntityFramework;
using Khd.Core.Wcs.Global;
using Masuit.Tools.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Khd.Core.Wcs.Wcs
{
    /// <summary>
    /// 二楼调度
    /// </summary>
    public class SecondFloor
    {
        List<BasePlcpoint> ScanPoint { get; set; }//点位信息
        private readonly IHost _host;
        private readonly Plc.S7.Plc _plc;
        BasePlcpoint? LineRFID { get; set; }
        BasePlcpoint? LineWcsrun { get; set; }
        BasePlcpoint? LineSignal { get; set; }
        BasePlcpoint? LineIsPallet { get; set; }
        BasePlcpoint? LineSerialNO { get; set; }
        BasePlcpoint? LineFeedSeriaNo { get; set; }
        Thread FlowPointThread;
        int FloorNo { get; set; }
        string EquipNo = "";
        public SecondFloor(IHost host, Plc.S7.Plc plc, int floor, string equipNo)
        {
            this._host = host;
            this._plc = plc;
            FloorNo = floor;
            EquipNo = equipNo;
            this.ScanPoint = StaticData.BasePlcpointList.Where(t => t.floorNo == floor).ToList();//加载当前站点所对应的点位
            this.LineRFID = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("RFID"));
            this.LineWcsrun = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("wcsrun"));
            this.LineSignal = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("linesignal"));
            this.LineIsPallet = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("ispallet"));
            this.LineSerialNO = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("serialno"));
            this.LineFeedSeriaNo = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("feedserialno"));

            //var lineRFID = this._plc.Read(NodeSettingCarNo.plcpointAddress);
            try
            {
                //默认启动,清理plc的上位机写入点位值
                this._plc.Write(LineRFID.plcpointAddress, MainCentralControl.QingKongDianWei);
            }
            catch (Exception ex)
            {
                Console.WriteLine("楼层" + floor + " 初始化数据异常" + ex.Message);
                LogManager.Error(ex);
            }
        }
        /// <summary>
        /// 启动上件扫描监听
        /// </summary>
        public void StartPoint()
        {

            FlowPointThread = new Thread(MonitorInLocatorPoint);
            FlowPointThread.Start();
        }

        public void MonitorInLocatorPoint()
        {
            using var scope = _host.Services.CreateScope();
            using var dbContext = scope.ServiceProvider.GetRequiredService<DefaultDbContext>();
            while (true)
            {
                try
                {
                    //入库任务
                    var rfid = this._plc.Read(LineRFID.plcpointAddress);
                    var isSignal = this._plc.Read(LineSignal.plcpointAddress);
                    var isPallet = this._plc.Read(LineIsPallet.plcpointAddress);
                    if (rfid != null && isSignal != null && isPallet != null)
                    {
                        //正常读到输送线信息 有到位信号,并且有托盘,获取条码信息
                        if (Convert.ToInt32(isSignal) > 0 && Convert.ToInt32(isPallet) == 1)
                        {
                            //获取条码信息
                            var palletNo = Convert.ToString(rfid);
                            //获取入库任务
                            var wcsTask = GetTask(palletNo, FloorNo, EquipNo);
                            //判断是否为出库任务
                            if (wcsTask.taskType == 2 || wcsTask.taskType == 3)
                            {
                                this._plc.Write(LineWcsrun.plcpointAddress, 1);
                                //更新任务下一点位为提升机
                                wcsTask.nextPointId = 6;
                                wcsTask.nextPointNo = "T01";
                                wcsTask.updateTime=DateTime.Now;
                                dbContext.Update(wcsTask);
                                dbContext.SaveChanges();
                            }
                            else
                            {
                                //入库任务
                                //下发agv任务
                                SendTask(wcsTask);
                            }
                        }
                    }

                }
                catch (Exception ex)
                {
                    LogManager.Error(ex);
                }
                finally
                {
                    Thread.Sleep(1000);
                }
            }
        }

        //获取输送线上的任务
        public WcsTask GetTask(string containerNo, int floorNo, string equipNo)
        {
            using var scope = _host.Services.CreateScope();
            using var dbContext = scope.ServiceProvider.GetRequiredService<DefaultDbContext>();
            var wcsTask = new WcsTask();
            var wareHouseList = StaticData.WmsBaseWarehouse.ToList();
            try
            {
                //获取条码号,如果该条码任务存在就继续任务,如果条码不存在,创建入库任务并调度agv
                var task = StaticData.WcsTask.Where(t => t.containerNo == containerNo).FirstOrDefault();
                if (task == null)
                {
                    var palletInfo = StaticData.MesBasePalletInfo.Where(t => t.palletInfoCode == containerNo).FirstOrDefault();
                    //查询该条码绑定的物料信息
                    var material = StaticData.WmsWarehouseMaterial.Where(t => t.storageId == palletInfo.materialId).FirstOrDefault();
                    var wareHouse = wareHouseList.Where(t => t.warehouseId == material.warehouseId).FirstOrDefault();
                    var dic = StaticData.BaseDictionary.Where(t => t.dicKey == "TaskType" && t.ud1 == "I" && t.dicField == wareHouse.warehouseInstockType).FirstOrDefault();
                    var equip = StaticData.BaseEquip.ToList();
                    var startEquip = equip.Where(t => t.equipNo == equipNo).FirstOrDefault();
                    var endPoint = wareHouseList.Where(t => t.warehouseFloor == floorNo).FirstOrDefault();
                    //var currEquip=
                    if (palletInfo != null)
                    {
                        //自动获取id
                        Jc.SnowId.JcSnowId id = new Jc.SnowId.JcSnowId(1, 1);
                        var objid = id.NextId();
                        WcsTask newTask = new()
                        {
                            objid = objid,
                            taskType = Convert.ToInt32(dic.dicValue),
                            containerNo = containerNo,
                            taskStatus = 0,
                            materialId = material.storageId,
                            qty = Convert.ToInt32(palletInfo.bindAmount),
                            startPointId = startEquip.objid,
                            startPointNo = equipNo,
                            currPointId = startEquip.objid,
                            currPointNo = equipNo,
                            endPointId = endPoint.warehouseId,
                            endPointNo = endPoint.warehouseCode,
                        };
                        dbContext.Add(newTask);
                        dbContext.SaveChanges();
                        wcsTask = newTask;
                    }
                    else
                    {
                        LogManager.Info(floorNo + "楼接驳位,托盘" + containerNo + "未绑定!");
                    }
                }
                else
                {
                    wcsTask = StaticData.WcsTask.Where(t => t.currPointNo == equipNo).FirstOrDefault();
                }
            }
            catch (Exception ex)
            {
                LogManager.Info(floorNo + "楼接驳位异常" + ex.Message);
                throw;
            }
            return wcsTask;
        }
        /// <summary>
        /// 下发任务
        /// </summary>
        /// <param name="task"></param>
        public void SendTask(WcsTask task)
        {
            using var scope = _host.Services.CreateScope();
            using var dbContext = scope.ServiceProvider.GetRequiredService<DefaultDbContext>();
            //入库类型
            List<int> taskInType = new List<int> { 1, 3, 5, 7 };
            List<int> taskOutType = new List<int> { 2, 4, 6, 8 };
            try
            {
                //获取
                if (task == null) return;
                if (taskInType.Contains(task.taskType.GetValueOrDefault()))
                {
                    //首先判断是否已下发指令
                    var cmd = StaticData.WcsCmd.Where(t => t.taskId == task.objid).FirstOrDefault();
                    //指令表存在说明已下发
                    if (cmd != null) return;
                    //获取下发agv指令
                    string ip = ""; int port = 0; string url = "";
                    RequestAGVTaskDto agvtask = new RequestAGVTaskDto();
                    agvtask.reqCode = task.serialNo.ToString();
                    var json = JsonConvert.SerializeObject(agvtask);
                    HttpHelper.SendPostMessage(ip, port, url, json);
                    //未下发给agv下发指令
                    WcsCmd taskCmd = new WcsCmd()
                    {
                        taskId = task.objid,
                        cmdType = task.taskType,
                        serialNo = task.serialNo,
                        equipmentNo = task.equipmentNo,
                        cmdStatus = 1,
                        createBy = "",
                        createTime = DateTime.Now,
                    };
                    dbContext.Add(taskCmd);
                    dbContext.SaveChanges();
                }
                else
                {

                }

            }
            catch (Exception)
            {

                throw;
            }
        }
    }
}
