using System;
using SimpleCore.Library;
using SimpleLite.RCS.CarTypes;
using StandardScene.Signal.Model;
using StandardScene.Signal.Plc;

namespace StandardScene.Signal.Logic
{
    /// <summary>
    /// 销钉 / 牵引棒升降后再放行。对齐反编译 <c>DefaultPlugin.PointControl</c>。
    /// </summary>
    /// <remarks>
    /// <c>SignalParams</c>：<c>动作;机构名</c>。
    /// 动作：<c>UP1</c> 升销钉1，<c>UP2</c> 升销钉1+2，<c>Down1</c> / <c>Down2</c> 对应下降。
    /// 机构名可选：填了则必须等该机构读字节=允许离开才启动；空则只等销钉动作完成。
    /// 销钉指令通过 <see cref="SignalCarAdapter.Control"/> 反射调用车体 MethodMember（如 SetPin1Up）。
    /// </remarks>
    public static class PointControlHandler
    {
        /// <summary>停稳：先判机构是否允许离开，再下发销钉，全部到位后启动。</summary>
        public static void OnStopped(Car car, SignalStopSpec spec, Func<string, string, PlcStationRuntime> find)
        {
            var action = spec.Action;
            var jgName = spec.JgName;
            if (string.IsNullOrEmpty(action))
            {
                Diagnosis.Log($"AGV{car.id}停在地标{SignalCarAdapter.PositionId(car)}，读取配置特殊点名称为空", "SetPin", true);
                return;
            }

            var waitLeave = false;
            if (!string.IsNullOrEmpty(jgName))
            {
                var rt = find(jgName, spec.DockId);
                if (rt != null)
                {
                    lock (rt.Sync)
                        waitLeave = rt.ReadSignal != SignalReadValue.允许离开;
                }
            }

            var pos = SignalCarAdapter.PositionId(car);
            switch (action)
            {
                case "UP1":
                    PinThenGo(car, pos, waitLeave, jgName, "SetPin1Up");
                    break;
                case "UP2":
                    PinThenGo(car, pos, waitLeave, jgName, "SetPin1Up", "SetPin2Up");
                    break;
                case "Down1":
                    PinThenGo(car, pos, waitLeave, jgName, "SetPin1Down");
                    break;
                case "Down2":
                    PinThenGo(car, pos, waitLeave, jgName, "SetPin1Down", "SetPin2Down");
                    break;
            }
        }

        /// <summary>
        /// 任一销钉未完成则本拍只下发指令、不启动；
        /// 全部完成且（无需等离开 或 已允许离开）才 Start。
        /// </summary>
        private static void PinThenGo(Car car, int pos, bool waitLeave, string jgName, params string[] actions)
        {
            var done = true;
            foreach (var a in actions)
            {
                if (!SignalCarAdapter.IsActionFinish(car, a))
                    done = false;
            }

            if (!done)
            {
                foreach (var a in actions)
                    SignalCarAdapter.Control(car, a);
                return;
            }

            if (waitLeave)
            {
                Diagnosis.Log($"AGV{car.id}停在地标{pos}，需要读取{jgName}工位的允许离开", "SetPin", true);
                return;
            }

            SignalCarAdapter.Start(car);
            Diagnosis.Log($"AGV{car.id}停在地标{pos}，牵引棒动作到位，已通知AGV启动", "SetPin", true);
        }
    }
}
