import { ObjectId, UUID } from "mongodb";
import DBSystem from "../../../types/db/DBSystem";
import { getPlanetById } from "../../db/planets";
import User from "../User";
import BuildingManager from "./BuildingManager";
import { Sector } from "./LocationManager";
import { Planet } from "./PlanetManager";
import PlanetResourceManager from "./PlanetResourceManager";
import PlanetShipManager from "./PlanetShipManager";
import StructureManager from "./StructureManager";
import SystemResourceManager from "./SystemResourceManager";
import SystemShipManager from "./SystemShipManager";
import PlanetDefenseManager from "./PlanetDefenseManager";
import SystemDefenseManager from "./SystemDefenseManager";
import SystemEnergyManager from "./SystemEnergyManager";
import PlanetEnergyManager from "./PlanetEnergyManager";
import AsteroidManager from "./AsteroidManager";
import Asteroid from "../../../types/Asteroid";

export type System = {
    _id: ObjectId,
    sector: Sector,
    name: string,
    ownedBy: User,
    structures: StructureManager,
    resources: SystemResourceManager,
    ships: SystemShipManager,
    defenses: SystemDefenseManager,
    planets: Planet[];
    asteroids: Asteroid[];
}

export default class SystemManager {
    planets: Planet[] = [];
    structures: StructureManager;
    resources: SystemResourceManager;
    ships: SystemShipManager;
    defenses: SystemDefenseManager;
    energy: SystemEnergyManager;
    asteroids: AsteroidManager;
    data: System;

    constructor(data: System) {
        this.data = data;
        this.structures = new StructureManager(this);
        this.resources = new SystemResourceManager(this);
        this.ships = new SystemShipManager(this);
        this.defenses = new SystemDefenseManager(this);
        this.energy = new SystemEnergyManager(this);
        this.asteroids = new AsteroidManager(this);
    }

    async fillData(systemData: DBSystem) {
        await this.structures.init(systemData.structures);
        await this.resources.init(systemData.resources);
        await this.ships.init(systemData.ships);
        await this.defenses.init(systemData.defenses);
        this.asteroids.init(systemData.asteroids);
        this.energy.update();

        await Promise.all(systemData.planets.map(async planetId => {
            const planet = await getPlanetById(planetId);

            const planetObject: Planet = {
                _id: planet._id,
                system: this,
                name: planet.name,
                fields: planet.fields,
                //@ts-ignore
                resources: null,
                //@ts-ignore
                buildings: null,
                //@ts-ignore
                ships: null,
                //@ts-ignore
                defenses: null,
                //@ts-ignore
                energy: null
            }

            planetObject.resources = await new PlanetResourceManager(planetObject).init(planet.resources);
            planetObject.buildings = await new BuildingManager(planetObject).init(planet.buildings);
            planetObject.ships = await new PlanetShipManager(planetObject).init(planet.ships);
            planetObject.defenses = await new PlanetDefenseManager(planetObject).init(planet.defenses);
            planetObject.energy = new PlanetEnergyManager(planetObject).update();

            this.planets.push(planetObject);
        }));

        return this;
    }

    addPlanet(planet: Planet) {
        this.planets.push(planet);
    }
}