using System;

namespace StandardScene
{
    /// <summary>
    /// 磁条管控区放行判定结果。由信号插件「磁条交管进程」填写，Mag2Car 在 StartStop=12 停稳后消费。
    /// </summary>
    public sealed class MagControlReleaseDecision
    {
        /// <summary>当前触发点在交管表里有启用规则。false 时 Mag2Car 回退地图 <c>Fass2_ControlArea</c> 字段。</summary>
        public bool RuleFound { get; set; }

        public bool CanRelease { get; set; }

        public string AreaId { get; set; } = string.Empty;

        public int Capacity { get; set; } = 1;

        public int OthersInArea { get; set; }

        /// <summary>放行后写入本车报文的 StartStop，通常 11（管控启动）或 1（过站）。</summary>
        public byte ReleaseStartStop { get; set; } = 11;

        public string Reason { get; set; } = string.Empty;
    }

    /// <summary>
    /// Mag2Car 与信号插件之间的管控放行钩子。不让 Magnetic / Signal 互相引用。
    /// </summary>
    /// <remarks>
    /// 磁条交管进程启动时 <see cref="Register"/>，停止时 <see cref="Unregister"/>。
    /// Mag2Car 在管控停止点调用 <see cref="TryCheck"/>：有规则用表判定，没有则用地图字段。
    /// </remarks>
    public static class MagControlReleaseHook
    {
        private static readonly object Sync = new object();
        private static object _owner;
        private static Func<int, int, MagControlReleaseDecision> _check;

        /// <summary>注册判定函数。<paramref name="owner"/> 用于停止时只清自己的注册。</summary>
        public static void Register(object owner, Func<int, int, MagControlReleaseDecision> check)
        {
            if (owner == null) throw new ArgumentNullException(nameof(owner));
            lock (Sync)
            {
                _owner = owner;
                _check = check;
            }
        }

        public static void Unregister(object owner)
        {
            if (owner == null) return;
            lock (Sync)
            {
                if (!ReferenceEquals(_owner, owner))
                    return;
                _owner = null;
                _check = null;
            }
        }

        /// <summary>
        /// 询问当前注册的交管进程。未注册返回 null；已注册但该触发点无规则时
        /// 返回 <see cref="MagControlReleaseDecision.RuleFound"/> = false。
        /// </summary>
        public static MagControlReleaseDecision TryCheck(int carId, int triggerSiteId)
        {
            Func<int, int, MagControlReleaseDecision> check;
            lock (Sync)
                check = _check;
            return check?.Invoke(carId, triggerSiteId);
        }
    }
}
