"use strict";
this.name = "GalCopBB_LifeSupport";
this.author = "phkb";
this.copyright = "2017 phkb";
this.description = "Controls handling of life support messages and functions";
this.license = "CC BY-NC-SA 4.0";

this._lifeSupportDefaultTime = 480; // default amount of time (in seconds) given to rescue entity before life support fails
this._lifeSupportTimer = null; // timer to control the life support checking process
this._lifeSupportRemaining = []; // array of dictionary objects that have details about each life support check in system
this._distressMessageTimer = null; // timer to control the transmission of a distress signal from an escape pod

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
	this._debug = worldScripts.GalCopBB_Missions._debug;
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillEnterWitchspace = function () {
	// if we jump out with any pods or stricken ships waiting for us they will all die
	if (this._lifeSupportTimer && this._lifeSupportTimer.isRunning) {
		// end life support on any entities in-system at the moment
		for (var i = 0; i < this._lifeSupportRemaining.length; i++) {
			this._lifeSupportRemaining[i].remaining = 1;
		}
		// force the check to happen (because we're about to turn the timers off, and we want to make sure all data is updated correctly)
		this.$lifeSupportCheck();
	}
	this.$stopTimers();
}

//-------------------------------------------------------------------------------------------------------------
this.shipDied = function (whom, why) {
	this.$stopTimers();
}

//-------------------------------------------------------------------------------------------------------------
// stop all timers
this.$stopTimers = function $stopTimers() {
	if (this._distressMessageTimer && this._distressMessageTimer.isRunning) this._distressMessageTimer.stop();
	delete this._distressMessageTimer;
	if (this._lifeSupportTimer && this._lifeSupportTimer.isRunning) this._lifeSupportTimer.stop();
	delete this._lifeSupportTimer;
}

//-------------------------------------------------------------------------------------------------------------
this.$addShip = function $addShip(obj) {
	if (obj.ent.script.hasOwnProperty("_missionID")) obj.ent.script._missionID_lifeSupport = obj.ent.script._missionID;
	this._lifeSupportRemaining.push(obj);
	if (this._distressMessageTimer == null || this._distressMessageTimer.isRunning === false) {
		this._distressMessageTimer = new Timer(this, this.$sendDistressMessage, 5, 5);
	}
	if (this._lifeSupportTimer == null || this._lifeSupportTimer.isRunning === false) {
		this._lifeSupportTimer = new Timer(this, this.$lifeSupportCheck, 5, 5);
	}
	this.$turnOffSpawningOXPs();
}

//-------------------------------------------------------------------------------------------------------------
// finds any ships in desperate state and send the player a comms message once they're in range
this.$sendDistressMessage = function $sendDistressMessage() {
	function gcm_findDistressTargets(entity) {
		return (entity.primaryRole === "gcm_stricken_ship" || entity.primaryRole === "gcm_stricken_pod" || entity.primaryRole === "gcm_runaway_pod");
	}
	var targets = system.filteredEntities(this, gcm_findDistressTargets);
	if (targets.length > 0) {
		for (var i = 0; i < targets.length; i++) {
			targets[i].throwSpark();
			// only send a message if the target has a crew
			if (targets[i].crew.length > 0) {
				if (player.ship.position.distanceTo(targets[i]) < 20000 & targets[i].script._sentDistress === false) {
					targets[i].script._sentDistress = true;
					targets[i].commsMessage(expandDescription("[distress_message_" + targets[i].primaryRole + "]"), player.ship);
				}
			}
		}
	} else {
		this._distressMessageTimer.stop();
	}
}

//-------------------------------------------------------------------------------------------------------------
// checks the level of life support remaining in any stricken ships or escape pods
// converts any entity that runs out of life support into a dead ship
this.$lifeSupportCheck = function $lifeSupportCheck() {
	var notify = [600, 540, 480, 420, 360, 300, 240, 180, 150, 120, 90, 60, 50, 40, 30, 20, 10, 5];

	var found = false;
	for (var i = 0; i < this._lifeSupportRemaining.length; i++) {
		if (this._lifeSupportRemaining[i].ent.isInSpace && this._lifeSupportRemaining[i].remaining > 0) {
			found = true;
			if (this._lifeSupportRemaining[i].ent.primaryRole === "gcm_stricken_ship" || this._lifeSupportRemaining[i].ent.hasRole("gcm_special_pod")) {
				this._lifeSupportRemaining[i].last = this._lifeSupportRemaining[i].remaining;
				this._lifeSupportRemaining[i].remaining -= 5;
				if (this._lifeSupportRemaining[i].remaining < 0) this._lifeSupportRemaining[i].remaining = 0;

				// determine when to notify player
				var transmit = "";
				for (var j = 0; j < notify.length; j++) {
					if (this._lifeSupportRemaining[i].remaining <= notify[j] && this._lifeSupportRemaining[i].last > notify[j]) transmit = expandDescription("[life_support_notify" + notify[j] + "]");
				}
				// determine when to send comms
				if (this._lifeSupportRemaining[i].remaining <= 60 && this._lifeSupportRemaining[i].comms === false) {
					this._lifeSupportRemaining[i].ent.commsMessage(expandDescription("[distress_hurry]"), player.ship);
					this._lifeSupportRemaining[i].comms = true;
				}

				if (this._lifeSupportRemaining[i].remaining === 0) {
					// dang it - out of time!
					if (this._lifeSupportRemaining[i].ent.hasRole("gcm_special_pod")) {
						// convert pod to derelict
						var shp = this._lifeSupportRemaining[i].ent;

						var retarget = false;
						if (player.ship.target === shp) retarget = true;
						var o = shp.orientation;
						var ep = shp.entityPersonality;
						var pos = shp.position;
						var ds = shp.desiredSpeed;
						var ms = shp.maxSpeed;
						var pr = shp.primaryRole;
						var mid = shp.script._missionID_lifeSupport;
						var vel = shp.velocity;

						shp.remove(true);

						// we should never get an instance where the new ship isn't created, but just in case...
						var checkShips = system.addShips("gcm_stricken_pod_dead", 1, pos, 0);
						var newshp = null;
						if (checkShips) newshp = checkShips[0];
						if (newshp) {
							newshp.orientation = o;
							newshp.entityPersonality = ep;
							newshp.maxSpeed = ms;
							newshp.desiredSpeed = ds;
							newshp.script._missionID_lifeSupport = mid;
							newshp.script.shipDied = this.$gcm_entity_shipDied;
							newshp.velocity = vel;

							if (pr === "gcm_stricken_pod") newshp.reactToAIMessage("START_TUMBLING");

							newshp.primaryRole = "gcm_derelict";
							newshp.setCrew(null);

							var item = worldScripts.BulletinBoardSystem.$getItem(newshp.script._missionID_lifeSupport);
							item.data.targetQuantity = 0;
							if (retarget) player.ship.target = newshp;
						}
					}
					if (this._lifeSupportRemaining[i].ent.primaryRole === "gcm_stricken_ship") {
						// convert ship to derelict
						var shp = this._lifeSupportRemaining[i].ent;
						// set script to default, to avoid a special script for the trader doing stuff. (like setting a new AI)
						shp.setScript("oolite-default-ship-script.js");
						if (shp.script.shipBeingAttacked) delete shp.script.shipBeingAttacked;

						shp.switchAI("oolite-nullAI.js");

						shp.script.shipLaunchedEscapePod = worldScripts.GalCopBB_Derelict.$gcm_derelict_shipLaunchedEscapePod; // function to remove the escapepod after launch.
						if (shp.equipmentStatus("EQ_ESCAPE_POD") === "EQUIPMENT_UNAVAILABLE") shp.awardEquipment("EQ_ESCAPE_POD");
						shp.abandonShip(); // make sure no pilot is left behind and this command turns the ship into cargo.
						shp.primaryRole = "gcm_derelict";
						var item = worldScripts.BulletinBoardSystem.$getItem(shp.script._missionID_lifeSupport);
						item.data.targetQuantity = 0;
						shp.displayName = shp.displayName + expandDescription("[gcm_no_life_signs]");
					}
					this.$restartSpawningOXPs();
				} else {
					if (transmit !== "") {
						player.consoleMessage(expandDescription("[gcm_life_support_remaining]", { amount: transmit, type: this._lifeSupportRemaining[i].type }), 5);
					}
				}
			}
		}
	}
	// if there were no ships with life support still active, stop the timer.
	if (found === false) {
		this._lifeSupportTimer.stop();
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$gcm_entity_shipDied = function $gcm_entity_shipDied(whom, why) {
	var gcm = worldScripts.GalCopBB_Missions;
	var bb = worldScripts.BulletinBoardSystem;

	if (gcm._debug) log(this.name, "running shipDied for " + this.ship + ": reason " + why + ", " + whom);
	if (this.ship.script.$gcm_hold_shipDied) this.ship.script.$gcm_hold_shipDied(whom, why);

	var item = bb.$getItem(this.ship.script._missionID_lifeSupport);
	if (item) item.data.destroyedQuantity = 1;
	if (gcm._distressMessageTimer && gcm._distressMessageTimer.isRunning) gcm._distressMessageTimer.stop();

	var ls = worldScripts.GalCopBB_LifeSupport;
	for (var i = 0; i < ls._lifeSupportRemaining.length; i++) {
		if (ls[i].ent == this.ship) {
			ls._lifeSupportRemaining[i].remaining = 0;
			break;
		}
	}
	ls.$restartSpawningOXPs();
}

//-------------------------------------------------------------------------------------------------------------
// turn off OXP's that will spawn ships in your path, as they will likely interfere too much with any mission
// where life support time is limited
this.$turnOffSpawningOXPs = function $turnOffSpawningOXPs() {
	if (worldScripts.spacecrowds) {
		if (this._debug) log(this.name, "turning off space crowds");
		worldScripts.spacecrowds.checkTimer.stop();
	}
	if (worldScripts.deep_space_pirates) {
		if (this._debug) log(this.name, "turning off deep space pirates");
		worldScripts.deep_space_pirates.checkTimer.stop();
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$restartSpawningOXPs = function $restartSpawningOXPs() {
	var found = false;
	for (var i = 0; i < this._lifeSupportRemaining.length; i++) {
		if (this._lifeSupportRemaining[i].remaining > 0) found = true;
	}
	if (found === true) return;
	if (worldScripts.spacecrowds) {
		if (this._debug) log(this.name, "restarting space crowds");
		worldScripts.spacecrowds.checkTimer.start();
	}
	if (worldScripts.deep_space_pirates) {
		if (this._debug) log(this.name, "restarting deep space pirates");
		worldScripts.deep_space_pirates.checkTimer.start();
	}
}