using SimpleCore;
using SimpleCore.PropType;
using Simple3.RCS.CarTypes;
using System;
using System.Collections.Generic;
using System.Linq;

namespace StandardScene.Magnetic.Tasking
{
    /// <summary>
    /// 按 holdingLocks + 物理 siteID 统计管控站点列表上的他车占用。
    /// </summary>
    internal static class Fass2ControlAreaOccupancy
    {
        public static Fass2ControlReleaseCheck Check(Car self, int controlSiteId)
        {
            var site = SimpleLib.GetSite(controlSiteId);
            var area = Fass2ControlAreaGate.Resolve(Fass2SiteFieldReader.Read(site), controlSiteId);
            var occupancies = new List<Fass2ControlOccupancy>();

            IEnumerable<AbstractCar> cars;
            try
            {
                cars = SimpleLib.GetAllCars();
            }
            catch (Exception ex)
            {
                return new Fass2ControlReleaseCheck
                {
                    CanRelease = false,
                    AreaId = area.AreaId,
                    Capacity = area.Capacity,
                    ReleaseStartStop = area.ReleaseStartStop,
                    Reason = "car list unavailable: " + ex.Message
                };
            }

            if (cars != null)
            {
                foreach (var other in cars.OfType<Car>())
                {
                    if (other == null)
                    {
                        continue;
                    }

                    occupancies.Add(new Fass2ControlOccupancy(other.id, CollectOccupiedSiteIds(other)));
                }
            }

            return Fass2ControlAreaGate.Evaluate(self?.id ?? 0, area, occupancies);
        }

        private static IReadOnlyList<int> CollectOccupiedSiteIds(Car car)
        {
            var ids = new List<int>();
            if (car.siteID > 0)
            {
                ids.Add(car.siteID);
            }

            var holding = car.status?.holdingLocks;
            if (holding == null)
            {
                return ids;
            }

            foreach (var lockId in holding)
            {
                if (lockId > 0 && !ids.Contains(lockId))
                {
                    ids.Add(lockId);
                }
            }

            return ids;
        }
    }
}
