"use strict";
this.name = "GalCopBB_EscapePods";
this.author = "phkb";
this.copyright = "2017 phkb";
this.description = "Control code for derelict/blackbox missions (missions 20/21/25)";
this.license = "CC BY-NC-SA 4.0";

this._periodicWaypointTimer = null; // timer to control the updating of periodic waypoints
this._maxLocations = 0;
this._setData = [];

//-------------------------------------------------------------------------------------------------------------
this.startUp = function () {
	var gcm = worldScripts.GalCopBB_Missions;
	// add these mission types into the main control
	var list = [20, 21, 25];
	gcm._availableMissionTypes = gcm._availableMissionTypes.concat(list);
	gcm._interstellarMissionTypes.push(21);
	// position 7 is not used in any of these mission types, so limit the possibilities 
	this._maxLocations = gcm._positions.length - 1;
}

//-------------------------------------------------------------------------------------------------------------
this.systemWillPopulate = function () {
	// reset the mission populator data array
	this._setData.length = 0;
	var gcm = worldScripts.GalCopBB_Missions;
	var list = gcm.$getListOfMissions(true, [20, 25]);

	if (list.length > 0) {
		// loop through all active missions and see if any need to be set up for this system
		for (var i = 0; i < list.length; i++) {
			// *** type 20 - escape pod
			if (list[i].data.missionType === 20 &&
				list[i].destination === system.ID &&
				list[i].data.quantity === 0 &&
				list[i].data.destroyedQuantity === 0 &&
				list[i].expiry > clock.adjustedSeconds) {

				// add the escape pod
				var position = gcm.$getRandomPosition(list[i].data.locationType, 0.1, list[i].ID).position;

				this._setData.push({
					missionType: 20,
					missionID: list[i].ID,
					source: list[i].source,
					target: list[i].data.targetQuantity,
					goons: 0,
					quantity: 0
				});

				// add pod with populator
				system.setPopulator("gcm-escape-pod-" + list[i].ID, {
					callback: function (pos) {
						var missData = worldScripts.GalCopBB_EscapePods.$getMissionData(20);
						var ep = null;
						var checkShips = null;
						for (var j = 1; j <= 5; j++) {
							checkShips = system.addShips((missData.target === 1 ? "gcm_stricken_pod" : "gcm_stricken_pod_dead"), 1, pos, 1000);
							if (checkShips) ep = checkShips[0];
							if (ep) break;
						}
						if (ep) {
							// make the escape pod look broken
							ep.maxSpeed = 0;
							ep.desiredSpeed = 0;
							ep.reactToAIMessage("START_TUMBLING");
							ep.script._missionID = missData.missionID;
							ep.script._sentDistress = false;
							// monkey patch if necessary
							// add our shipDied event to the escape pod
							if (ep.script.shipDied) ep.script.$gcm_hold_shipDied = ep.script.shipDied;
							ep.script.shipDied = worldScripts.GalCopBB_EscapePods.$gcm_entity_shipDied;

							if (missData.target === 1) {
								// add occupant
								ep.setCrew({
									name: randomName() + " " + randomName(),
									insurance: parseInt(Math.random() * 100 + 50),
									bounty: 0,
									origin: missData.source,
									seed: "0 0 0 0 " + missData.source + " 2"
								});
								ep.script._missionID_lifeSupport = ep.script._missionID;
								worldScripts.GalCopBB_LifeSupport.$addShip({
									ent: ep,
									type: expandDescription("[gcm_damaged_escape_pod]"),
									remaining: Math.floor(Math.random() * 120 + worldScripts.GalCopBB_LifeSupport._lifeSupportDefaultTime),
									last: 0,
									comms: false
								});
							} else {
								ep.setCrew(null);
							}
						} else {
							log("galcopBB_escapepods", "!!ERROR: Escape pod not spawned!");
						}
						// spawn some alloy wreckage as well
						system.addShips("scarred-alloy", (Math.floor(Math.random() * 5) + 2), pos, 5000);

					}.bind(this),
					location: "COORDINATES",
					coordinates: position
				});

				if (gcm._debug) gcm.$setWaypoint(position, [0, 0, 0, 0], "D", "Debug position (20)", "20");
			}

			// *** type 25 - runaway escape pod
			if (list[i].data.missionType === 25 &&
				list[i].destination === system.ID &&
				list[i].data.quantity === 0 &&
				list[i].data.destroyedQuantity === 0 &&
				list[i].expiry > clock.adjustedSeconds) {

				this._setData.push({
					missionType: 25,
					missionID: list[i].ID,
					source: list[i].source,
					goons: 0,
					target: list[i].data.targetQuantity,
					quantity: 0
				});

				// add pod with populator
				system.setPopulator("gcm-escape-pod-" + list[i].ID, {
					callback: function (pos) {
						var missData = worldScripts.GalCopBB_EscapePods.$getMissionData(25);
						var ep = null;
						var checkShips = null;
						for (var j = 1; j <= 5; j++) {
							checkShips = system.addShips((missData.target === 1 ? "gcm_runaway_pod" : "gcm_stricken_pod_dead"), 1, pos, player.ship.scannerRange);
							if (checkShips) ep = checkShips[0];
							if (ep) break;
						}
						if (ep) {
							// give the escape pod some serious speed
							ep.maxSpeed = player.ship.maxSpeed * player.ship.injectorSpeedFactor - 100;
							ep.maxThrust = 0; // make the pod frictionless
							// give the escape pod a heading and velocity
							ep.orientation = Quaternion.random();
							ep.desiredSpeed = ep.maxSpeed;

							ep.script._missionID = missData.missionID;
							ep.script._sentDistress = false;
							// add our shipDied event to the escape pod
							// monkey patch if necessary
							if (ep.script.shipDied) ep.script.$gcm_hold_shipDied = ep.script.shipDied;
							ep.script.shipDied = worldScripts.GalCopBB_EscapePods.$gcm_entity_shipDied;

							// add occupant
							if (missData.target === 1) {
								ep.setCrew({
									name: randomName() + " " + randomName(),
									insurance: parseInt(Math.random() * 100 + 50),
									bounty: 0,
									origin: missData.source,
									seed: "0 0 0 0 " + missData.source + " 2"
								});
								ep.script._missionID_lifeSupport = ep.script._missionID;
								worldScripts.GalCopBB_LifeSupport.$addShip({
									ent: ep,
									type: expandDescription("[gcm_runaway_escape_pod]"),
									remaining: Math.floor(Math.random() * 120 + worldScripts.GalCopBB_LifeSupport._lifeSupportDefaultTime * 0.75),
									last: 0,
									comms: false
								});
							} else {
								ep.setCrew(null);
							}
						} else {
							log("galcopBB_escapepods", "!!ERROR: Escape pod not spawned!");
						}
					}.bind(this),
					location: "INNER_SYSTEM_OFFPLANE",
					locationSeed: list[i].ID
				});

				// start periodic waypoint
				this._periodicWaypointTimer = new Timer(this, this.$startPeriodicWaypoint, 10, 0);
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.interstellarSpaceWillPopulate = function () {
	var gcm = worldScripts.GalCopBB_Missions;
	var list = gcm.$getListOfMissions(true, 21);
	if (list.length > 0) {
		// loop through all active missions and see if any need to be set up for this system
		for (var i = 0; i < list.length; i++) {
			// *** type 21 - escape pod in interstellar
			if (list[i].data.missionType === 21 &&
				((gcm._fromSystem === list[i].destination || gcm._fromSystem === list[i].source) &&
					(gcm._toSystem === list[i].destination || gcm._toSystem === list[i].source)) &&
				list[i].data.quantity === 0 &&
				list[i].data.destroyedQuantity === 0 &&
				list[i].expiry > clock.adjustedSeconds) {

				// add the escape pod somewhere just inside scanner range
				var dist = (Math.random() * (player.ship.scannerRange * 0.2)) + (player.ship.scannerRange * 0.75);
				var dir = Vector3D.randomDirection(dist);
				var position = Vector3D(0, 0, 0).add(dir);

				this._setData.push({
					missionType: 21,
					missionID: list[i].ID,
					source: list[i].source,
					target: list[i].data.targetQuantity,
					goons: 0,
					quantity: 0
				});

				// add pod with populator
				system.setPopulator("gcm-escape-pod-" + list[i].ID, {
					callback: function (pos) {
						var missData = worldScripts.GalCopBB_EscapePods.$getMissionData(21);
						var ep = null;
						var checkShips = null;
						for (var j = 1; j <= 5; j++) {
							checkShips = system.addShips((missData.target === 1 ? "gcm_stricken_pod" : "gcm_stricken_pod_dead"), 1, pos, 1)
							if (checkShips) ep = checkShips[0];
							if (ep) break;
						}
						if (ep) {
							// make the escape pod look broken
							ep.maxSpeed = 0;
							ep.desiredSpeed = 0;
							ep.script._missionID = missData.missionID;
							ep.script._sentDistress = false;
							ep.reactToAIMessage("START_TUMBLING");
							// monkey patch if necessary
							// add our shipDied event to the escape pod
							if (ep.script.shipDied) ep.script.$gcm_hold_shipDied = ep.script.shipDied;
							ep.script.shipDied = worldScripts.GalCopBB_EscapePods.$gcm_entity_shipDied;

							// add occupant
							if (missData.target === 1) {
								ep.setCrew({
									name: randomName() + " " + randomName(),
									insurance: parseInt(Math.random() * 100 + 50),
									bounty: 0,
									origin: missData.source,
									seed: "0 0 0 0 " + missData.source + " 2"
								});
								// configure the life support countdown for this ship
								ep.script._missionID_lifeSupport = ep.script._missionID;
								worldScripts.GalCopBB_LifeSupport.$addShip({
									ent: ep,
									type: expandDescription("[gcm_damaged_escape_pod]"),
									remaining: Math.floor(Math.random() * 60 + worldScripts.GalCopBB_LifeSupport._lifeSupportDefaultTime / 5),
									last: 0,
									comms: false
								});
							} else {
								ep.setCrew(null);
							}

						} else {
							log("galcopBB_escapepods", "!!ERROR: Escape pod not spawned!");
						}
						// spawn some alloy wreckage as well
						system.addShips("scarred-alloy", (Math.floor(Math.random() * 5) + 2), pos, 5000);
					}.bind(this),
					location: "COORDINATES",
					coordinates: position
				});
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillEnterWitchspace = function () {
	this.$stopTimers();
}

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

//-------------------------------------------------------------------------------------------------------------
this.shipScoopedOther = function (whom) {
	if (!whom || !whom.isValid) return;
	var gcm = worldScripts.GalCopBB_Missions;
	if (whom.hasRole("gcm_special_pod") === true) {
		var bb = worldScripts.BulletinBoardSystem;
		var item = bb.$getItem(whom.script._missionID);

		if (item && item.data.targetQuantity === 1) {
			item.data.quantity = 1;
			bb.$updateBBMissionPercentage(item.ID, 1);

			gcm.$logMissionData(item.ID);
			player.consoleMessage(expandDescription("[goal_updated]"));

			gcm._storedClientName = whom.crew[0].name;
			if (worldScripts.GalCopBB_Missions_MFD._escapePod == null) {
				gcm.$postScoopMissionCreation(whom.script._missionID, 7);
				if (whom.script.shipWasDumped) whom.script.$gcmovr_shipWasDumped = whom.script.shipWasDumped;
				whom.script.shipWasDumped = worldScripts.GalCopBB_Missions_MFD.$gcmmfd_shipWasDumped;
				worldScripts.GalCopBB_Missions_MFD._escapePod = whom;
			}
		}
		return;
	}
	if (whom.primaryRole === "escape-capsule" && whom.script.hasOwnProperty("_gcm_already_asked") == false) {
		// this is a generic escape capsule
		// work out what type of rescue it is (bounty or insurance)
		// straight insurance job
		if (whom.crew && whom.crew[0].insuranceCredits > 0 && whom.crew[0].legalStatus === 0 &&
			(gcm._newMissionDelayTimer == null || gcm._newMissionDelayTimer.isRunning === false)) {
			// consider adding a secondary mission
			// use a negative to make the routine run as if a type 20 (escape pod) mission has just been completed
			if (Math.random() > 0.8 && worldScripts.GalCopBB_Missions_MFD._escapePod == null) { // 0.8
				gcm._storedClientName = whom.crew[0].name;
				gcm.$postScoopMissionCreation(-20, 7);
				if (whom.script.shipWasDumped) whom.script.$gcmovr_shipWasDumped = whom.script.shipWasDumped;
				whom.script.shipWasDumped = worldScripts.GalCopBB_Missions_MFD.$gcmmfd_shipWasDumped;
				worldScripts.GalCopBB_Missions_MFD._escapePod = whom;
			}
		}
		// straight bounty claim
		if (whom.crew && whom.crew[0].insuranceCredits === 0 && whom.crew[0].legalStatus > 0) {
			// do we have any secondary missions a pirate would want to initiate?
		}
		// set a flag so that if the player dumps and then rescoops the capsule we don't keep getting new mission offers.
		whom.script._gcm_already_asked = true;
	}
}

//-------------------------------------------------------------------------------------------------------------
// handles shipDied for escape pod (20) missions
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);
	if (item) item.data.destroyedQuantity = 1;
}

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

//-------------------------------------------------------------------------------------------------------------
// turns on an intermittent waypoint at the last known location of the runaway escape pod
this.$startPeriodicWaypoint = function $startPeriodicWaypoint() {
	var pods = system.shipsWithPrimaryRole("gcm_runaway_pod");
	if (pods && pods.length > 0) {
		for (var i = 0; i < pods.length; i++) {
			worldScripts.GalCopBB_Missions.$setWaypoint(pods[i].position, pods[i].orientation, "E", expandDescription("[gcm_runaway_escape_pod_title]"), "runaway_" + pods[i].script._missionID);
		}
		this._periodicWaypointTimer = new Timer(this, this.$endPeriodicWaypoint, Math.floor(Math.random() * 10) + 10, 0);
		player.consoleMessage(expandDescription("[gcm_escape_pod_nav_beacon_on]"))
	}
}

//-------------------------------------------------------------------------------------------------------------
// turns off the intermittent waypoint
this.$endPeriodicWaypoint = function $endPeriodicWaypoint() {
	if (worldScripts.GalCopBB_Missions.$removeSpecialWaypoint("_runaway") === true) {
		player.consoleMessage(expandDescription("[gcm_escape_pod_nav_beacon_off]"))
		// set timer to turn them on again
		this._periodicWaypointTimer = new Timer(this, this.$startPeriodicWaypoint, Math.floor(Math.random() * 10) + 10, 0);
	}
}

//-------------------------------------------------------------------------------------------------------------
// gets mission specific data for the populator routines
// this works on a first in/first out basis - if there are multiple missions of the same type being populated, the mission specific data would
// get pushed in to the setData array in order, and then this routine pulls that data out in the same order
// that's the theory, anyway!
this.$getMissionData = function $getMissionData(missionType) {
	for (var i = 0; i < this._setData.length; i++) {
		if (this._setData[i].missionType === missionType) {
			var result = {
				missionID: this._setData[i].missionID,
				trueMissionType: (this._setData[i].trueMissionType ? this._setData[i].trueMissionType : missionType),
				source: this._setData[i].source,
				goons: this._setData[i].goons,
				quantity: this._setData[i].quantity,
				target: this._setData[i].target
			};
			this._setData.splice(i, 1);
			return result;
		}
	}
	return null;
}

//-------------------------------------------------------------------------------------------------------------
// 20 - rescue damaged escape pod
this.$missionType20_Values = function $missionType20_Values(workTime, routeTime, routeDistance, destSysInfo) {
	var result = {};
	// pick a location
	result["locationType"] = Math.floor(Math.random() * this._maxLocations);
	result["quantity"] = 1;
	result["price"] = parseInt((parseInt(Math.random() * 50) + 100) / 10) * 10 + (7 - destSysInfo.government) * 50 +
		worldScripts.GalCopBB_CoreMissionValues.$calcDistanceBonus(routeDistance, 10) // plus a distance bonus
		+
		worldScripts.GalCopBB_CoreMissionValues.$calcPlayerBonus(500); // plus a possible bonus price, based on player score 
	result["expiry"] = clock.adjustedSeconds + routeTime + workTime; // transit time + 1 hour to complete
	result["penalty"] = parseInt(result.price / 2);
	return result;
}

//-------------------------------------------------------------------------------------------------------------
// 21 - rescue stranded escape pod interstellar
this.$missionType21_Values = function $missionType21_Values(workTime, routeTime, routeDistance, destSysInfo) {
	var result = {};
	result["quantity"] = 1;
	result["price"] = parseInt((parseInt(Math.random() * 500) + 500) / 10) * 10 +
		worldScripts.GalCopBB_CoreMissionValues.$calcDistanceBonus(routeDistance, 10) // plus a distance bonus
		+
		worldScripts.GalCopBB_CoreMissionValues.$calcPlayerBonus(1000); // plus a possible bonus price, based on player score 
	result["expiry"] = clock.adjustedSeconds + routeTime + workTime; // transit time + 1 hour to complete
	result["penalty"] = parseInt(result.price / 2);
	return result;
}

//-------------------------------------------------------------------------------------------------------------
// 25 - rescue runaway escape pod
this.$missionType25_Values = function $missionType25_Values(workTime, routeTime, routeDistance, destSysInfo) {
	var result = {};
	result["quantity"] = 1;
	result["price"] = parseInt((parseInt(Math.random() * 50) + 100) / 10) * 10 + (7 - destSysInfo.government) * 50 +
		worldScripts.GalCopBB_CoreMissionValues.$calcDistanceBonus(routeDistance, 10) // plus a distance bonus
		+
		worldScripts.GalCopBB_CoreMissionValues.$calcPlayerBonus(500); // plus a possible bonus price, based on player score 
	result["expiry"] = clock.adjustedSeconds + routeTime + workTime; // transit time + 1 hour to complete
	result["penalty"] = parseInt(result.price / 2);
	return result;
}