// Docking controller script; handles docking and undocking.
// Specifically, when you activate the script it will:
//   * Connect any Connectors whose names start with "Docking Port" that are ready to connect.
//   * Turn off all engines.
//   * Set all O2 and Hydrogen tanks to Stockpile.
//
// Recharging batteries needs to be done manually, since the script can't finish with the
//   batteries disabled.
//
// When you activate the script with "-undock" it will reverse all of these actions.
//
// TODO: None of the below switches work yet.
// You can selectively disable some functionality with switches.
//   * "-no-refuel" to disable refueling

MyCommandLine cli;
IEnumerator<bool> state;

List<IMyShipConnector> dockingPorts;
List<IMyThrust> thrusters;
List<IMyGasTank> tanks;

public Program() {
    cli = new MyCommandLine();
    state = null;

    dockingPorts = new List<IMyShipConnector>();
    List<IMyShipConnector> allConnectors = new List<IMyShipConnector>();
    GridTerminalSystem.GetBlocksOfType(allConnectors);
    foreach(IMyShipConnector connector in allConnectors) {
        if (connector.CustomName.StartsWith("Docking Port")) {
            dockingPorts.Add(connector);
        }
    }

    thrusters = new List<IMyThrust>();
    GridTerminalSystem.GetBlocksOfType(thrusters);

    tanks = new List<IMyGasTank>();
    GridTerminalSystem.GetBlocksOfType(tanks);

    Echo($"Found {dockingPorts.Count} docking ports.");
    Echo($"Found {thrusters.Count} thrusters");
    Echo($"Found {tanks.Count} tanks");
}

public void Main(string argument, UpdateType updateSource) {
    if (state == null) {
        cli.TryParse(argument);
        if (cli.Switch("undock")) state = Undock();
        else state = Dock();
        Runtime.UpdateFrequency = UpdateFrequency.Update100;
        return;
    }

    if (!state.MoveNext()) {
        Runtime.UpdateFrequency = UpdateFrequency.None;
        state.Dispose();
        state = null;
    }
}

private IEnumerator<bool> Dock() {
    Echo("Initiating docking operation.");

    foreach (IMyShipConnector dockingPort in dockingPorts) {
        if (dockingPort.Status == MyShipConnectorStatus.Connectable) {
            dockingPort.Connect();
        }
    }

    bool docked = false;
    while (!docked) {
        yield return true;
        foreach (IMyShipConnector dockingPort in dockingPorts) {
            if (dockingPort.Status == MyShipConnectorStatus.Connected) {
                docked = true;
                break;
            }
        }
    }

    Echo("Docking clamp engaged. Shutting down systems.");

    foreach (IMyThrust thruster in thrusters) {
        thruster.Enabled = false;
    }

    foreach (IMyGasTank tank in tanks) {
        tank.Stockpile = true;
    }

    yield return false;
}

private IEnumerator<bool> Undock() {
    Echo("Initiating undocking operation.");
    foreach (IMyGasTank tank in tanks) {
        tank.Stockpile = false;
    }

    foreach (IMyThrust thruster in thrusters) {
        thruster.Enabled = true;
    }

    foreach (IMyShipConnector dockingPort in dockingPorts) {
        if (dockingPort.Status == MyShipConnectorStatus.Connected) {
            dockingPort.Disconnect();
        }
    }

    yield return false;
}