using SimpleCore.Compiler;
using SimpleCore.PropType;
using StandardScene.CarTypes;

namespace StandardScene.Coders
{
    /// <summary>
    /// 通用（导航无关）轨道 coder 基类。
    ///
    /// 背景：避障/IO/纠偏等 coder 原以 [TemplateTrackCoderSettings] 内联重复在各车型上。
    /// 这里把它们抽离为单一可复用实现，各车型改用 [ProgramTrackCoderSettings] 按各自 priority 引用。
    ///
    /// 等价性：内部仍走内核 Template 机制（ProgramCoderHelper.PrepareTrackEngine + Topaz 求值），
    /// useVerb / templateString 与原模板逐字一致；这些 coder 仅引用 Basic 字段，故统一用 BasicXxxFields，
    /// 与原先传车型 Fields 在“模板所引用字段”上行为一致。priority 由引用方车型特性指定，执行顺序不变。
    /// </summary>
    public abstract class CommonTemplateTrackCoder : ITrackCoder
    {
        protected abstract string UseVerb { get; }
        protected abstract string TemplateString { get; }

        // 默认仅用 Basic 字段袋；个别 coder（如避障含 ChangeAvoidanceParam 标志位）可覆写站点字段袋。
        protected virtual System.Type SiteFieldsType => typeof(BasicSiteFields);

        public virtual bool toBlock() => false;

        public bool Code(SegmentPlan plan, Track track, Site src, Site dst, int i)
        {
            var engine = ProgramCoderHelper.PrepareTrackEngine(plan, track, src, dst, i,
                carFields: typeof(BasicCarFields),
                siteFields: SiteFieldsType,
                trackFields: typeof(BasicTrackFields),
                planFields: typeof(BasicPlanFields));

            if (!(engine.ExecuteExpression(UseVerb) is bool ok) || !ok)
                return false;

            plan.codeArr[i] += (string)engine.ExecuteExpression("`" + TemplateString + "`");
            return false;
        }
    }

    // 原 useVerb: track.LidarArea != -2
    public class LidarAreaSwitchCoder : CommonTemplateTrackCoder
    {
        protected override string UseVerb => "track.LidarArea != -2";
        protected override string TemplateString =>
            "agv.Queue(()=>{},()=>{ agv.SwitchLidarArea(${track.LidarArea}); });";
    }

    // 原无 useVerb（等价 true，每段执行）
    public class AvoidanceDistanceCoder : CommonTemplateTrackCoder
    {
        protected override string UseVerb => "true";
        protected override string TemplateString =>
            "agv.Queue(()=>{},()=>{ agv.ChangeAvoidanceDistance(${track.StopDistance},${track.SlowDistance}); });";
    }

    // 原 useVerb: track.IOArea != -1
    public class IoAreaSwitchCoder : CommonTemplateTrackCoder
    {
        protected override string UseVerb => "track.IOArea != -1";
        protected override string TemplateString =>
            "agv.Queue(()=>{},()=>{ agv.SwitchIoArea(${track.IOArea}); });";
    }

    // 原 useVerb: track.BiasAlarmThresh >0 || track.DthAlarmThresh > 0
    public class TrackingErrThreshCoder : CommonTemplateTrackCoder
    {
        protected override string UseVerb => "track.BiasAlarmThresh >0 || track.DthAlarmThresh > 0";
        protected override string TemplateString =>
            "agv.Queue(()=>{},()=>{ agv.ChangeTrackingErrThresh(${track.BiasAlarmThresh},${track.DthAlarmThresh}); });";
    }

    // 避障区尺寸切换（4 参，含中心点）站点字段袋：在 Basic 基础上补 ChangeAvoidanceParam 标志位。
    // 等价于 MWL/MultiVehicle 原用的 MultiWheelLifterSiteFields 中本 coder 实际引用到的字段。
    internal class AvoidanceParamSiteFields : BasicSiteFields
    {
        public bool ChangeAvoidanceParam = false;
    }

    /// <summary>
    /// 避障区尺寸切换 coder（4 参，含中心点）。
    /// 合并自 MultiWheelLifterCar 与 MultiVehicleCar 两份**逐字相同**的内联模板（零行为变更）：
    ///   useVerb=dst.ChangeAvoidanceParam==true；模板=ChangeAvoidanceParam(L,W,CenterX,CenterY)。
    /// 注：Kiva / Forklift 的 2 参变体见同文件 AvoidanceParamLWCoder（方案 B：4 参 flag 版 + 2 参 L,W 版）。
    /// </summary>
    public class AvoidanceParamCoder : CommonTemplateTrackCoder
    {
        protected override System.Type SiteFieldsType => typeof(AvoidanceParamSiteFields);
        protected override string UseVerb => "dst.ChangeAvoidanceParam==true";
        protected override string TemplateString =>
            "agv.Queue(()=>{},()=>{ agv.ChangeAvoidanceParam(${dst.CarLength},${dst.CarWidth},${dst.CarCenterX},${dst.CarCenterY}); });";
    }

    /// <summary>
    /// 避障区尺寸切换 coder（2 参，无中心点）。
    /// 合并自 Kiva 与 Forklift 两份**逐字相同**的 2 参内联模板。
    /// 触发条件统一取 Forklift 的「已配置车体长宽」(dst.CarLength!=-1 &amp;&amp; dst.CarWidth!=-1)：
    ///   - Forklift：useVerb/模板逐字一致，行为不变；
    ///   - Kiva：原为无条件触发，统一后当站点未配置长宽(=-1)时不再下发 ChangeAvoidanceParam(-1,-1)，
    ///     属预期内的安全收敛（方案 B，见 StandardScene拆分计划.md §11.4-2）。
    /// 仅引用 Basic 字段（CarLength/CarWidth 已在 BasicSiteFields），故用默认 BasicSiteFields。
    /// </summary>
    public class AvoidanceParamLWCoder : CommonTemplateTrackCoder
    {
        protected override string UseVerb => "dst.CarLength != -1 && dst.CarWidth != -1";
        protected override string TemplateString =>
            "agv.Queue(()=>{},()=>{ agv.ChangeAvoidanceParam(${dst.CarLength},${dst.CarWidth}); });";
    }
}
