"use strict";
this.name = "PlanetFall2_Shipyards";
this.author = "phkb";
this.copyright = "CC-BY-SA-NC 4.0";
this.description = "Controls shipyard populations";

/*
    This script moves the majority of ships on orbital station shipyards to planetary shipyards instead.
*/
this.index = 0; // indicates where in the process we're up to.
this.transferred = false; // indicates whether the transfer process has completed
this.shipTransfer = false; // indicates whether we're up to the actual ship transfer part
this.mainShipyards = [];
this.otherShipyards = [];
this.orbitalShipyards = [];

//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
    if (this.index != -1) {
        missionVariables.PlanetFall2_ShipyardTransfer = (this.transferred == true ? "1" : "0");
        missionVariables.PlanetFall2_ShipTransferPhase = (this.shipTransfer == true ? "1" : "0")
        missionVariables.PlanetFall2_ShipyardProgress = this.index;
    }
}

//-------------------------------------------------------------------------------------------------------------
this.systemWillPopulate = function () {
    this.mainShipyards.length = 0
    this.otherShipyards.length = 0;
    this.orbitalShipyards.length = 0;
    if (system.government == 0) {
        this.transferred = true;
        this.index = -1;
    }
}

//-------------------------------------------------------------------------------------------------------------
this.startUp = function () {
    this.playerShipKeys = Ship.keysForRole("player");

    if (missionVariables.PlanetFall2_ShipyardProgress) {
        this.index = parseInt(missionVariables.PlanetFall2_ShipyardProgress);
    } else {
        this.index = -1;
    }
    if (this.index != -1) {
        if (missionVariables.PlanetFall2_ShipyardTransfer) this.transferred = (missionVariables.PlanetFall2_ShipyardTransfer == "0" ? false : true);
        if (missionVariables.PlanetFall2_ShipTransferPhase) this.shipTransfer = (missionVariables.PlanetFall2_ShipTransferPhase == "0" ? false : true);
    } else {
        this.transferred = true;
        this.shipTransfer = false;
    }
    delete missionVariables.PlanetFall2_ShipyardProgress;
    delete missionVariables.PlanetFall2_ShipyardTransfer;
    delete missionVariables.PlanetFall2_ShipTransferPhase;
    if (!worldScripts.PlanetFall2._config.moveShipyards) this.transferred = true;
}

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function() {
    this.shipDockedWithStation();
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillEnterWitchspace = function() {
    // if shipyards are being moved, reset the flag to indicate the transfer hasn't happened yet
    if (worldScripts.PlanetFall2._config.moveShipyards) {
        this.transferred = false;
        this.index = 0;
    }
}

//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function() {
    if (worldScripts.PlanetFall2._config.moveShipyards && this.transferred == false) {
        this._timer0 = new Timer(this, this.$moveShipsFromShipyards.bind(this), 3, 0);
    }
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function() {
    // stop everything if we launch - too much stuttering
    this.$stopTimers();
}

//-------------------------------------------------------------------------------------------------------------
this.$stopTimers = function() {
    if (this._timer0 && this._timer0.isRunning) this._timer0.stop();
    if (this._timer1 && this._timer1.isRunning) this._timer1.stop();
    if (this._timer2 && this._timer2.isRunning) this._timer2.stop();
}

//-------------------------------------------------------------------------------------------------------------
this.$moveShipsFromShipyards = function $moveShipsFromShipyards() {
    function mainPlanetShipyards(entity) { return (entity.isStation && entity.hasRole("planetFall2_mainSurface") && entity.hasShipyard) };
    function otherPlanetShipyards(entity) { return (entity.isStation && entity.hasRole("planetFall2_subSurface") && entity.hasShipyard) };
    function stationShipyards(entity) { return (entity.isStation && !entity.hasRole("planetFall2_surface") && entity.maxSpeed == 0 && !entity.scriptInfo["planetFall_leaveShipyard"] && entity.hasShipyard) };
    // first, get a set of planet stations with shipyards
    // including secondary planets
    if (this.mainShipyards.length == 0) this.mainShipyards = system.filteredEntities(system.stations, mainPlanetShipyards);
    if (this.otherShipyards.length == 0) this.otherShipyards = system.filteredEntities(system.stations, otherPlanetShipyards);
    if (this.orbitalShipyards.length == 0) {
        this.orbitalShipyards = system.filteredEntities(system.stations, stationShipyards);
        // if we're docked at an orbital shipyard, we only need to process that station
        // if we aren't docked at an orbital shipyard, we need to process everything
        if (this.orbitalShipyards.indexOf(player.ship.dockedStation) >= 0) {
            // empty the orbital shipyards array, then add a single station
            this.orbitalShipyards.length = 0;
            this.orbitalShipyards.push(player.ship.dockedStation);
        }
    }
    if (this.orbitalShipyards.length == 0) return; // no orbitals with shipyards
    if (this.mainShipyards.length == 0 && this.otherShipyards.length == 0) return; // no planet sites with shipyards (should be *very* rare)
    // only reset the index if it's in the "finished" state
    if (this.index == -1) this.index = 0;
    // we'll process each station one at a time to limit slowdowns
    if (this.shipTransfer == true) {
        this._timer2 = new Timer(this, this.$processStationShips.bind(this), 0.3, 0);
        return;
    }
    log(this.name + ".debug", "initialising station shipyards");
    if (this._timer1 && this._timer1.isRunning) this._timer1.stop();
    this._timer1 = new Timer(this, this.$processStation.bind(this), 1.5, 0);
}

//-------------------------------------------------------------------------------------------------------------
// all we're doing first is forcing shipyards to populate, one station at a time
this.$processStation = function $processStation() {
    // if we've got to the end of populating shipyards, we can now start the process of moving ships
    if (this.index > this.orbitalShipyards.length - 1) {
        this.index = 0;
        this.shipTransfer = true;
        log(this.name + ".debug", "station shipyards setup complete");
        log(this.name + ".debug", "starting shipyards transfer process")
        this._timer2 = new Timer(this, this.$processStationShips.bind(this), 0.3, 0);
        return;
    }
    var stn = this.orbitalShipyards[this.index];
    // set up for the next station now, in case the shipyard creation runs overtime
    this.index += 1;
    if (this._timer1 && this._timer1.isRunning) this._timer1.stop();
    this._timer1 = new Timer(this, this.$processStation.bind(this), 1.5, 0);
    var num = stn.shipyard.length; // force shipyard to load
}

//-------------------------------------------------------------------------------------------------------------
// once all the stations have a populated shipyard, we do things one ship at a time to prevent timeouts
this.$processStationShips = function $processStationShips() {
    if (this.index > this.orbitalShipyards.length - 1) {
        this.transferred = true;
        this.shipTransfer = false;
        this.index = -1;
        log(this.name + ".debug", "processing shipyards complete");
        return;
    }
    var skeys = this.playerShipKeys;
    var stn = this.orbitalShipyards[this.index];
    var i = stn.shipyard.length - 1;
    if (i >= 0) {
        // work out if we're going to stop now
        if (i < 2) {
            // 33% chance of stopping when 2 ships remain
            // 67% chance of stopping when 1 ship remains
            if (Math.random() > ((i + 1) / 3)) {
                i = -1;
            }
        } 
        if (i >= 0) {
            var shp = stn.shipyard[i];
            // if the data key for this ship isn't in the list of player keys, skip the adding process and just delete it
            // the player wouldn't be able to fly it anyway
            if (skeys.indexOf(shp.shipdata_key) >= 0) {
                // build up the object from the source
                var obj = {};
                obj.short_description = shp.short_description;
                obj.shipdata_key = shp.shipdata_key;
                obj.price = shp.price;
                obj.personality = shp.personality;
                obj.extras = (shp.extras ? shp.extras : []);

                //log(this.name + ".debug", "station " + stn);
                // pick a destination, with weighting towards main planet
                if (Math.random() < 0.75 || this.otherShipyards.length == 0) {
                    var idx = Math.floor(Math.random() * this.mainShipyards.length);
                    //log(this.name + ".debug", "main yards shipkey " + obj.shipdata_key);
                    if (this.mainShipyards.length - 1 > idx) {
                        this.mainShipyards[idx].addShipToShipyard(obj);
                    }
                } else {
                    var idx = Math.floor(Math.random() * this.otherShipyards.length);
                    //log(this.name + ".debug", "other yards shipkey " + obj.shipdata_key);
                    this.otherShipyards[idx].addShipToShipyard(obj);
                }
            }
            // remove the ship from the source
            stn.removeShipFromShipyard(i);
        }
    }
    if (i <= 0) {
        // set up for the next station
        this.index += 1;
    }
    this._timer2 = new Timer(this, this.$processStationShips.bind(this), 0.3, 0);
}
