using LessokajiWeaverUtilities.Utilities;
using SimpleLite.RCS;
using SimpleLite.RCS.CarTypes;
using SimpleCore;
using SimpleCore.Compiler;
using SimpleCore.PropType;
using StandardScene.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StandardScene.CarTypes
{
    class SiteFields
    {
        public float FetchSpeed = 0;
        public float FetchLiftDownTarget = -1;
        public float FetchLiftUpTarget = -1;
        public float PutSpeed = 0;
        public float PutLiftDownTarget = -1;
        public float PutLiftUpTarget = -1;
        public float LeaveShelfSpeed = 0;
        public float LeaveShelfLiftDownTarget = -1;
        public bool Shelf = false;
    }

    class TrackFields
    {
        public int ReverseDst = -1;
    }

    class PlanFields
    {
        public string action = "/";
    }

    //[TemplateTrackCoderSettings(
    //    priority = 20,
    //    useVerb = "src.Shelf&&plan.curSeg==1",
    //    templateString = "agv.Wait();agv.LeaveShelf(${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id},${src.LeaveShelfSpeed},${src.LeaveShelfLiftDownTarget});agv.Wait();",
    //    blockVerb = "true",
    //    siteFields = typeof(SiteFields),
    //    trackFields = typeof(TrackFields),
    //    planFields = typeof(PlanFields))]
    [TemplateTrackCoderSettings(
        priority = 20,
        useVerb = "plan.action=='fetch' && dst.Shelf&&plan.curSeg==plan.segN-2",
        templateString = "agv.Wait();agv.Fetch(${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id},${dst.FetchSpeed},${dst.FetchLiftDownTarget},${dst.FetchLiftUpTarget});agv.Wait();",
        blockVerb = "true",
        siteFields = typeof(SiteFields),
        trackFields = typeof(TrackFields),
        planFields = typeof(PlanFields))]
    [TemplateTrackCoderSettings(
        priority = 20,
        useVerb = "plan.action=='put' && dst.Shelf&&plan.curSeg==plan.segN-2",
        templateString = "agv.Wait();agv.Put(${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id},${dst.FetchSpeed},${dst.FetchLiftDownTarget},${dst.FetchLiftUpTarget});agv.Wait();",
        blockVerb = "true",
        siteFields = typeof(SiteFields),
        trackFields = typeof(TrackFields),
        planFields = typeof(PlanFields))]


    [CarType(Name = "多舵轮叉车", editor = typeof(MultiWheelForkLifter))]
    [I18N.DocumentTranslation(Name = "MultiWheel ForkLift Car", locale = "en")]
    public class MultiWheelForkLifter : GhostCar
    {
        public static async Task<MultiWheelForkLifter> Create()
        {
            var car = new MultiWheelForkLifter()
            {
                lstatus = "连接中",
                address = "127.0.0.1",
                name = "多舵轮叉车",
                haveCoordination = true,
                speed = 1
            };
            return car;
        }
        public static string GetCarStatus(Car car, string key)
        {
            string value = "0";
            if (car == null) return value;
            if (car.status.enums.TryGetValue(key, out var valueStr))
                value = valueStr;
            return value;
        }
        public override string SetDisplayInfo()
        {
            try
            {
                var str = $"{name}({id})\n";
                status.enums.TryGetValue("ChassisMode", out var manual);
                var ms = manual == "0" ? "自动" : "手动";
                status.enums.TryGetValue("Soc", out var soc);
                str = $"{str}{ms}|soc:{soc}";
                var alarmStr = GetCarStatus(this, "AlarmInfo");
                if (alarmStr != "")
                    str = $"{str}|{alarmStr}";
                if (status.enums.TryGetValue("ElectricCurrent", out var electricCurrent) &&
                    !string.IsNullOrEmpty(electricCurrent))
                {
                    var charging = float.Parse(electricCurrent) * 0.01f > 0 ? "充电中" : "未充电";
                    str = $"{str}|charge:{charging}";
                }

                var thresSpeed = Commons.CarValue(this, "ThresSpeed");
                str = $"{str}{((thresSpeed <= 0) ? "|避障触发" : "")}";
                return str;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return "bad car";
            }
        }

        private bool _running = false;
        [MethodMember(Name = "test")]
        public async void Test()
        {
            _running = true;
            var siteA = SimpleLib.GetAllSites().First(s => s.name == "A");
            var siteB = SimpleLib.GetAllSites().First(s => s.name == "B");
            var siteC = SimpleLib.GetAllSites().First(s => s.name == "C");
            while (_running)
            {
                var fetchPlan = new SegmentPlan() { usingCar = this };
                fetchPlan.fields["action"] = "fetch";
                fetchPlan.FindRoute(SimpleLib.GetSite(GetLastSite()), siteA);
                await fetchPlan.Compile("fetch").Queue();
                var putPlan = new SegmentPlan() { usingCar = this };
                putPlan.fields["action"] = "put";
                putPlan.FindRoute(SimpleLib.GetSite(GetLastSite()), siteB);
                await putPlan.Compile("put").Queue();
                var plan = new SegmentPlan() { usingCar = this };
                plan.FindRoute(SimpleLib.GetSite(GetLastSite()), siteC);
                await plan.Compile("go").Queue();
                var fetchPlan2 = new SegmentPlan() { usingCar = this };
                fetchPlan2.fields["action"] = "fetch";
                fetchPlan2.FindRoute(SimpleLib.GetSite(GetLastSite()), siteB);
                await fetchPlan2.Compile("fetch").Queue();
                var putPlan2 = new SegmentPlan() { usingCar = this };
                putPlan2.fields["action"] = "put";
                putPlan2.FindRoute(SimpleLib.GetSite(GetLastSite()), siteA);
                await putPlan2.Compile("put").Queue();
                var plan2 = new SegmentPlan() { usingCar = this };
                plan2.FindRoute(SimpleLib.GetSite(GetLastSite()), siteC);
                await plan2.Compile("go").Queue();

            }
        }
    }
}
