using System;

namespace StandardScene.Fass2Simulator
{
    public static class Fass2SimSelfTests
    {
        public static int Run(string[] args)
        {
            if (HasArg(args, "--motion-test"))
            {
                return RunMotionSelfTest();
            }

            if (HasArg(args, "--action-test"))
            {
                return RunActionSelfTest();
            }

            return 1;
        }

        private static int RunMotionSelfTest()
        {
            Fass2SimFileLogger.Configure(new Fass2SimConfig { EnableFileLog = false });
            var config = new Fass2SimConfig
            {
                InitialNode = 1,
                DefaultSegmentDistance = 500,
                DefaultSpeed = 500,
                AutoContinueOnPass = true
            };
            var (vehicle, motion, _) = Fass2SimBootstrap.CreateTestStack(config);
            var nodes = new[]
            {
                new Fass2SimNodeMessage { Node = 1, StartStop = 1, Distance = 500 },
                new Fass2SimNodeMessage { Node = 2, StartStop = 1, Distance = 500 },
                new Fass2SimNodeMessage { Node = 3, StartStop = 2 }
            };

            vehicle.State = 1;
            motion.OnNodesCommand(1001, nodes);

            for (var i = 0; i < 30; i++)
            {
                motion.Tick(200);
                var snap = vehicle.Snapshot();
                if (snap.Node == 3 && snap.State == 2)
                {
                    Console.WriteLine($"motion self-test ok: node={snap.Node}, task={snap.Task}");
                    return 0;
                }
            }

            var last = vehicle.Snapshot();
            Console.WriteLine($"motion self-test failed: node={last.Node}, state={last.State}, task={last.Task}");
            return 1;
        }

        private static int RunActionSelfTest()
        {
            Fass2SimFileLogger.Configure(new Fass2SimConfig { EnableFileLog = false });
            var config = new Fass2SimConfig
            {
                InitialNode = 3,
                ActionDelayMs = 500,
                AutoCompleteStationActions = false
            };
            var (vehicle, _, actions) = Fass2SimBootstrap.CreateTestStack(config);
            vehicle.State = 2;
            vehicle.Node = 3;
            vehicle.Lift = 0;

            var station = new Fass2SimNodeMessage
            {
                Node = 3,
                StartStop = Fass2SimActionResolver.StartStopStop,
                Lift = 1
            };
            actions.OnStationArrival(station);

            var pendingBefore = Fass2SimActionResolver.DescribePending(station, vehicle.Snapshot());
            if (string.IsNullOrEmpty(pendingBefore) || vehicle.Lift != 0)
            {
                Console.WriteLine($"action self-test failed at setup: pending={pendingBefore}, lift={vehicle.Lift}");
                return 1;
            }

            actions.OnActionCommand(2001, new Fass2SimNodeMessage { Node = 3, Lift = 1 });

            for (var i = 0; i < 10; i++)
            {
                actions.Tick(100);
            }

            var snap = vehicle.Snapshot();
            if (snap.Lift == 1 && actions.IsStationComplete())
            {
                Console.WriteLine($"action self-test ok: node={snap.Node}, lift={snap.Lift}");
                return 0;
            }

            Console.WriteLine(
                $"action self-test failed: lift={snap.Lift}, complete={actions.IsStationComplete()}, pending={Fass2SimActionResolver.DescribePending(station, snap)}");
            return 1;
        }

        private static bool HasArg(string[] args, string name)
        {
            if (args == null)
            {
                return false;
            }

            foreach (var arg in args)
            {
                if (string.Equals(arg, name, StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
            }

            return false;
        }
    }
}
