import {Thruster, THRUSTER_LIST, THRUSTER_TYPE_LIST} from "$lib/thruster.svelte";
import {Grid} from "$lib/grid";
import {INVENTORIES, Inventory} from "$lib/containers.svelte";
import type {Fuel} from "$lib/fuel";
import type {CargoMaterial} from "$lib/materials";

export class Ship {
    thrusters: Array<Thruster> = $state([]);
    inventories: Array<Inventory> = $state([]);
    grid: Grid = $state(Grid.Small);
    tons: number = $state(0);

    constructor(grid: Grid = Grid.Small) {
        this.grid = grid;
    }

    save() {
        return {
            thrusters: this.thrusters.map((thruster) => {
                return thruster.details.key;
            }),
            inventories: this.inventories.map((inventory) => {
                return inventory.details.key;
            }),
            grid: this.grid,
            weight: this.tons,
        }
    }

    load(ship: {
        grid: Grid,
        thrusters: Array<string>,
        inventories: Array<string>,
        weight: number,
    }) {
        if (ship.grid !== undefined) {
            this.grid = ship.grid;
        }

        if (ship.thrusters !== undefined) {
            this.thrusters = ship.thrusters.map((thruster) => {
                return new Thruster(THRUSTER_LIST[thruster]);
            });
        }

        if (ship.inventories !== undefined) {
            this.inventories = ship.inventories.map((inventory) => {
                return new Inventory(INVENTORIES[inventory]);
            });
        }

        if (ship.weight !== undefined) {
            this.tons = ship.weight;
        }
    }

    addThruster(thruster: Thruster): void {
        this.thrusters.push(thruster);
    }

    addInventory(inventory: Inventory): void {
        this.inventories.push(inventory);
    }

    getTotalVolume(inventoryMultiplier: number) {
        let volume = 0;
        this.inventories.forEach((inventory) => {
            volume += inventory.getVolume(this.grid, inventoryMultiplier)
        });
        return volume;
    }

    removeThruster(index: number): void {
        this.thrusters.splice(index, 1);
    }

    removeInventory(index: number): void {
        this.inventories.splice(index, 1);
    }

    getTotalThrust(atmosphere: number): number {
        let thrust: number = 0;
        this.thrusters.forEach((thruster) => {
            thrust += thruster.getThrust(this.grid, atmosphere);
        });
        return thrust;
    }

    getFuelTypes(): Array<Fuel> {
        let fuels: Array<Fuel> = [];
        this.thrusters.forEach((thruster) => {
            if (!fuels.includes(thruster.details.type.details.fuel)) {
                fuels.push(thruster.details.type.details.fuel)
            }
        })
        return fuels;
    }

    getTotalWeightPossible(gravity: number, atmosphere: number): number {
        return this.getTotalThrust(atmosphere) / (gravity * 9.81)
    }

    getVehicleWeightPossible(gravity: number, atmosphere: number, inventoryMultiplier: number, material: CargoMaterial): number {
        return this.getTotalWeightPossible(gravity, atmosphere) - this.getTotalVolume(inventoryMultiplier) * material.density;
    }

    getVehicleWeight(): number {
        return (this.tons * 1000);
    }

    getTotalWeight(inventoryMultiplier: number, material: CargoMaterial) {
        return this.getVehicleWeight() + this.getTotalVolume(inventoryMultiplier) * material.density;
    }

    getAcceleration(atmosphere: number, inventoryMultiplier: number, material: CargoMaterial) {
        console.log(material)
        return this.getTotalThrust(atmosphere) / this.getTotalWeight(inventoryMultiplier, material)
    }

    getMaxAcceleration(atmosphere: number) {
        return this.getTotalThrust(atmosphere) / this.getVehicleWeight();
    }
}