using System;
using System.Linq;
using SimpleCore.Library;
using StandardScene.Signal.Model;

namespace StandardScene.Signal.Plc
{
    /// <summary>读写字节转换与四套自动离站，对齐反编译 PLCManager。</summary>
    public static class PlcStationLogic
    {
        public static SignalReadValue ConvertRead(byte val) => val switch
        {
            1 => SignalReadValue.允许进入,
            2 => SignalReadValue.允许离开,
            _ => SignalReadValue.无状态
        };

        public static SignalWriteValue ConvertWrite(byte val) => val switch
        {
            1 => SignalWriteValue.进入中,
            2 => SignalWriteValue.到位,
            3 => SignalWriteValue.离开中,
            4 => SignalWriteValue.已离开,
            _ => SignalWriteValue.无状态
        };

        public static bool ContainsSite(string csv, int siteId)
        {
            if (string.IsNullOrWhiteSpace(csv) || siteId <= 0)
                return false;
            return csv.Split(new[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries)
                .Any(s => int.TryParse(s.Trim(), out var n) && n == siteId);
        }

        public static void AutoLeave(PlcStationRuntime rt)
        {
            if (rt?.Config == null) return;
            switch (rt.Config.LineType)
            {
                case SignalLineType.上线机构:
                    AutoLeaveUpLine(rt);
                    break;
                case SignalLineType.单牵引下线机构:
                    AutoLeaveDownLine(rt, pin2: false);
                    break;
                case SignalLineType.双牵引下线机构:
                    AutoLeaveDownLine(rt, pin2: true);
                    break;
                case SignalLineType.等待通行机构:
                    AutoLeaveWaitSit(rt);
                    break;
            }
        }

        private static void ClearLeft(PlcStationRuntime rt, bool fromReadback)
        {
            rt.WriteSignal = SignalWriteValue.无状态;
            rt.InAgvNo = 0;
            if (rt.RequestInAgvNo > 0)
            {
                Diagnosis.Log(
                    $"{rt.Config.JgName} {(fromReadback ? "回读已离开" : "写已离开成功")}，清空请求进入车 {rt.RequestInAgvNo}",
                    "JGControl", true);
                rt.RequestInAgvNo = 0;
            }
            else
                Diagnosis.Log($"{rt.Config.JgName} 已离开，清空信号", "JGControl", true);
        }

        private static void AutoLeaveUpLine(PlcStationRuntime rt)
        {
            if (rt.WriteSuccess && rt.WriteSignal == SignalWriteValue.已离开)
                ClearLeft(rt, fromReadback: false);
            if (rt.ReadWriteSignal == SignalWriteValue.已离开)
                ClearLeft(rt, fromReadback: true);

            if (rt.WriteSuccess && rt.WriteSignal == SignalWriteValue.进入中)
            {
                var car = SignalCarAdapter.Find(rt.RequestInAgvNo);
                if (car == null) return;
                if (!ContainsSite(rt.Config.JgInContains, SignalCarAdapter.PositionId(car)))
                {
                    rt.WriteSignal = SignalWriteValue.到位;
                    rt.InAgvNo = car.id;
                    rt.RequestInAgvNo = 0;
                    Diagnosis.Log($"AGV{car.id} 已到达机构 {rt.Config.JgName}", "JGControl", true);
                }
            }
            else if (rt.WriteSuccess && rt.WriteSignal == SignalWriteValue.到位)
            {
                var car = SignalCarAdapter.Find(rt.InAgvNo);
                if (car == null || SignalCarAdapter.IsRunning(car))
                    rt.WriteSignal = SignalWriteValue.离开中;
            }
            else if (rt.WriteSuccess && rt.WriteSignal == SignalWriteValue.离开中)
            {
                var car = SignalCarAdapter.Find(rt.InAgvNo);
                if (car == null || !ContainsSite(rt.Config.JgContains, SignalCarAdapter.PositionId(car)))
                    rt.WriteSignal = SignalWriteValue.已离开;
            }
        }

        private static void AutoLeaveDownLine(PlcStationRuntime rt, bool pin2)
        {
            if (rt.WriteSuccess && rt.WriteSignal == SignalWriteValue.已离开)
            {
                ClearLeft(rt, fromReadback: false);
                return;
            }

            if (rt.ReadWriteSignal == SignalWriteValue.已离开)
                ClearLeft(rt, fromReadback: true);

            if (rt.InAgvNo == 0) return;
            var car = SignalCarAdapter.Find(rt.InAgvNo);
            if (car == null) return;

            var pos = SignalCarAdapter.PositionId(car);
            if (rt.ReadSignal == SignalReadValue.允许离开 && pos == rt.Config.JgPointId)
            {
                if (rt.WriteSignal == SignalWriteValue.离开中) return;
                var pinOk = SignalCarAdapter.IsActionFinish(car, "SetPin1Up")
                            && (!pin2 || SignalCarAdapter.IsActionFinish(car, "SetPin2Up"))
                            && SignalCarAdapter.IsActionFinish(car, "StopCharge");
                if (pinOk)
                {
                    SignalCarAdapter.StopCharge(car);
                    SignalCarAdapter.Start(car);
                    rt.WriteSignal = SignalWriteValue.离开中;
                    Diagnosis.Log($"{rt.Config.JgName} 允许离开，通知 AGV{car.id} 启动，写离开中", "JGControl", true);
                }
                else
                {
                    SignalCarAdapter.Control(car, "SetPin1Up");
                    if (pin2) SignalCarAdapter.Control(car, "SetPin2Up");
                    SignalCarAdapter.Control(car, "StopCharge");
                }
            }
            else if (!string.IsNullOrEmpty(rt.Config.JgContains)
                     && !ContainsSite(rt.Config.JgContains, pos)
                     && rt.ReadWriteSignal != SignalWriteValue.已离开)
            {
                rt.WriteSignal = SignalWriteValue.已离开;
            }
        }

        private static void AutoLeaveWaitSit(PlcStationRuntime rt)
        {
            if (rt.WriteSuccess && rt.WriteSignal == SignalWriteValue.已离开)
            {
                ClearLeft(rt, fromReadback: false);
                return;
            }

            if (rt.ReadWriteSignal == SignalWriteValue.已离开)
                ClearLeft(rt, fromReadback: true);

            if (rt.InAgvNo == 0) return;
            var car = SignalCarAdapter.Find(rt.InAgvNo);
            if (car == null) return;

            var pos = SignalCarAdapter.PositionId(car);
            if (rt.ReadSignal == SignalReadValue.允许离开 && pos == rt.Config.JgPointId)
            {
                if (rt.WriteSignal == SignalWriteValue.离开中) return;
                if (SignalCarAdapter.IsActionFinish(car, "StopCharge"))
                {
                    SignalCarAdapter.Start(car);
                    rt.WriteSignal = SignalWriteValue.离开中;
                    Diagnosis.Log($"{rt.Config.JgName} 允许离开，通知 AGV{car.id} 启动，写离开中", "JGControl", true);
                }
                else
                    SignalCarAdapter.Control(car, "StopCharge");
            }
            else if (!string.IsNullOrEmpty(rt.Config.JgContains)
                     && !ContainsSite(rt.Config.JgContains, pos)
                     && rt.ReadWriteSignal != SignalWriteValue.已离开)
            {
                rt.WriteSignal = SignalWriteValue.已离开;
            }
        }
    }
}
