namespace ReactorMaintenance.Simulation;

public enum EEditorTool
{
    Floor,
    Wall,
    Reactor,
    CoolingPump,
    Generator,
    PressureRegulator,
    DiagnosticTerminal,
    ControlTerminal,
    CoolantPipe,
    FuelPipe,
    PressurePipe,
    Leak,
    Repair,
    Heat,
    Fire,
    Robot
}

public static class LevelEditor
{
    public static LevelState Apply(LevelState level, GridPosition position, EEditorTool tool)
    {
        if (!level.InBounds(position))
            return level;

        if (tool == EEditorTool.Robot)
            return level.GetCell(position).IsWalkable ? level with { Robot = position } : level;

        var cell = level.GetCell(position);
        cell = tool switch {
            EEditorTool.Floor => cell with { Terrain = ECellTerrain.Floor },
            EEditorTool.Wall => cell with {
                Terrain = ECellTerrain.Wall,
                Prop = ECellProp.None,
                Pipe = EPipeMedium.None,
                Flow = Balancing.Current.MinHazardValue,
                Pressure = Balancing.Current.MinHazardValue,
                LeakRate = Balancing.Current.MinHazardValue,
                PipeOpen = false,
                Powered = false
            },
            EEditorTool.Reactor => cell with { Terrain = ECellTerrain.Floor, Prop = ECellProp.Reactor },
            EEditorTool.CoolingPump => cell with {
                Terrain = ECellTerrain.Floor,
                Prop = ECellProp.CoolingPump,
                Powered = true
            },
            EEditorTool.Generator => cell with {
                Terrain = ECellTerrain.Floor,
                Prop = ECellProp.Generator,
                Powered = true
            },
            EEditorTool.PressureRegulator => cell with { Terrain = ECellTerrain.Floor, Prop = ECellProp.PressureRegulator },
            EEditorTool.DiagnosticTerminal => cell with {
                Terrain = ECellTerrain.Floor,
                Prop = ECellProp.DiagnosticTerminal,
                Powered = true
            },
            EEditorTool.ControlTerminal => cell with {
                Terrain = ECellTerrain.Floor,
                Prop = ECellProp.ControlTerminal,
                Powered = true
            },
            EEditorTool.CoolantPipe => cell with {
                Pipe = EPipeMedium.Coolant,
                Flow = Balancing.Current.DefaultPipeFlow,
                Pressure = Balancing.Current.DefaultPipePressure,
                Integrity = Math.Max(cell.Integrity, Balancing.Current.DefaultEditedPipeIntegrity),
                PipeOpen = true
            },
            EEditorTool.FuelPipe => cell with {
                Pipe = EPipeMedium.Fuel,
                Flow = Balancing.Current.DefaultPipeFlow,
                Pressure = Balancing.Current.DefaultPipePressure,
                Integrity = Math.Max(cell.Integrity, Balancing.Current.DefaultEditedPipeIntegrity),
                PipeOpen = true
            },
            EEditorTool.PressurePipe => cell with {
                Pipe = EPipeMedium.Pressure,
                Flow = Balancing.Current.DefaultPressurePipeFlow,
                Pressure = Balancing.Current.DefaultPressurePipePressure,
                Integrity = Math.Max(cell.Integrity, Balancing.Current.DefaultEditedPipeIntegrity),
                PipeOpen = true
            },
            EEditorTool.Leak => cell with {
                LeakRate = Math.Max(Balancing.Current.MinimumLeakRate, cell.LeakRate),
                Integrity = Math.Min(cell.Integrity, Balancing.Current.DamagedPipeIntegrity)
            },
            EEditorTool.Repair => cell with {
                LeakRate = Balancing.Current.RepairedLeakRate,
                Integrity = Balancing.Current.DefaultCellIntegrity,
                Hazards = cell.Hazards with {
                    Fire = false,
                    ElectricalCharge = Balancing.Current.RepairedElectricalCharge
                }
            },
            EEditorTool.Heat => cell with { Hazards = cell.Hazards with { Heat = Rules.Clamp(cell.Hazards.Heat + Balancing.Current.HeatToolIncrease) } },
            EEditorTool.Fire => cell with {
                Hazards = cell.Hazards with {
                    Fire = !cell.Hazards.Fire,
                    Heat = Math.Max(cell.Hazards.Heat, Balancing.Current.FireToolMinimumHeat),
                    Smoke = Math.Max(cell.Hazards.Smoke, Balancing.Current.FireToolMinimumSmoke)
                }
            },
            _ => cell
        };

        if (cell.Terrain == ECellTerrain.Wall)
            cell = cell with { Hazards = new() };

        return level.SetCell(position, cell);
    }
}