using Sandbox.ModAPI.Ingame;
using SpaceEngineers.Game.ModAPI.Ingame;
using System.Collections;
using System.Collections.Generic;
using VRageMath;

namespace IngameScript
{
    partial class Program
    {
        public class AirZone
        {
            public string Name { get; private set; }
            public bool Triggered { get; set; } = false;
            public List<IMyAirVent> Vents { get; } = new List<IMyAirVent>();

            private Program _program;
            private List<IMyDoor> _doors = new List<IMyDoor>();
            private List<IMyTextSurface> _displays = new List<IMyTextSurface>();
            private List<IMyLightingBlock> _lights = new List<IMyLightingBlock>();
            private PrefixedConsole _console;
            private Sequencer _sequencer;

            private const float TriggerLevel = 0.75F;

            public AirZone(Program program, string zoneName)
            {
                Name = zoneName;
                _program = program;
                _console = new PrefixedConsole(_program.Console, Name);
                _sequencer = new Sequencer(_program, Name);
            }

            public void AddBlock(IMyTerminalBlock block)
            {
                if (block is IMyAirVent)
                {
                    Vents.Add(block as IMyAirVent);
                }
                else if (block is IMyDoor)
                {
                    _doors.Add(block as IMyDoor);
                    SequenceableDoor wrapped = SequenceableFactory.MakeSequenceable(
                        _program,
                        block as IMyDoor,
                        "airMonitor") as SequenceableDoor;
                    wrapped.Step = 0;
                    wrapped.DeployOpen = false;
                    wrapped.LockOpen = false;
                    wrapped.LockClosed = true;
                    _sequencer.AddBlock(wrapped);
                }
                else if (block is IMyLightingBlock)
                {
                    _lights.Add(block as IMyLightingBlock);
                }
                else
                {
                    _console.Print("Tried to add incompatible block '{block.CustomName}'");
                }
                // TODO: support for arbitrary (sub-)sequences here could be powerful
            }

            public void Reset()
            {
                _console.Print("Resetting sensor.");
                Triggered = false;
            }

            // This enumerator should run forever.
            public IEnumerator<bool> Monitor()
            {
                while (true)
                {
                    foreach (IMyAirVent vent in Vents)
                    {
                        if (vent.GetOxygenLevel() < TriggerLevel) Triggered = true;
                    }

                    // TODO: add informational lights per-zone
                    if (Triggered == true)
                    {
                        _console.Print($"Low pressure alarm triggered.");
                        foreach (IMyLightingBlock light in _lights)
                        {
                            light.Enabled = true;
                            light.Color = Color.Red;
                        }

                        // close the doors
                        IEnumerator<bool> job = _sequencer.RunSequence(true);
                        while (job.MoveNext())
                        {
                            // It would be nice if the API had UpdateFrequency.Once10, e.g. "re-run in 10 ticks and then clear the flag"
                            // We'll just monitor every tick instead.
                            _program.Runtime.UpdateFrequency |= UpdateFrequency.Once;
                            yield return true;
                        }
                        job.Dispose();

                        while (Triggered) yield return true;

                        // unlock the doors, but we'll leave them closed.
                        foreach (IMyDoor door in _doors) { door.Enabled = true; }

                        foreach (IMyLightingBlock light in _lights)
                        {
                            light.Enabled = true;
                            light.Color = Color.White;
                        }
                    }

                    yield return true;
                }
            }
        }
    }
}