"use strict";
this.name = "GalCopBB_MeetShip";
this.author = "phkb";
this.copyright = "2017 phkb";
this.description = "Controls ship interactions for missions 30/32";
this.license = "CC BY-NC-SA 4.0";

this._commsNPC = null; // reference to the ship that is sending a comms message to the player
this._contactPoint = null; // holding object, containing the ship that is about to give the player a new mission
this._contactPointTimer = null; // timer to control the transmission of the new mission
this._deliveryPoint = null; // holding object, containing reference to ship to whom data is being transmitted
this._deliveryPointTimer = null; // timer to control the transmission of data to the target
this._checkPlayerNearbyTimer = null; // timer to check if the player is nearby
this._setData = [];

//-------------------------------------------------------------------------------------------------------------
this.startUp = function () {
	var gcm = worldScripts.GalCopBB_Missions;
	// add these mission types into the main control
	var list = [30, 32];
	gcm._availableMissionTypes = gcm._availableMissionTypes.concat(list);
	this._debug = gcm._debug;
}

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

	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 30 - fly to waypoint, meet ship
			if (list[i].data.missionType === 30 &&
				list[i].destination === system.ID &&
				list[i].data.quantity === 0 &&
				list[i].data.targetQuantity > 0 &&
				list[i].data.destroyedQuantity === 0 &&
				list[i].expiry > clock.adjustedSeconds) {

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

				// add ship with populator
				system.setPopulator("gcm-meet-ship-" + list[i].ID, {
					callback: function (pos) {
						var ms = worldScripts.GalCopBB_MeetShip;
						var missData = ms.$getMissionData(30);
						var gcm = worldScripts.GalCopBB_Missions;
						var gns = worldScripts.GalCopBB_GoonSquads;
						// 3 possibilities:
						// 1 - ship is there, ready to receive (types, 1,2,3,4,5,7,9)
						// 2 - it's a trap! player is attacked by pirates (type 6)
						// 3 - no ship at all - mission is a bust (types 8, 10)
						var type = parseInt(Math.random() * 15) + 1;
						switch (type) {
							case 1:
							case 2:
							case 3:
							case 4:
							case 5:
							case 7:
							case 8:
							case 9:
							case 10:
							case 11:
							case 12:
							case 13:
							case 14:
							case 15:
								var shp = null;
								var checkShips = null;
								for (var j = 1; j <= 5; j++) {
									checkShips = system.addShips("[" + gcm.$getRandomShipKey(parseInt(missData.missionID), 0) + "]", 1, pos, 3000);
									if (checkShips) shp = checkShips[0];
									if (shp) break;
								}
								if (shp) {
									if (gcm._rsnInstalled) shp.shipUniqueName = gcm.$getRandomShipName(shp, "trader");
									shp.bounty = 0;
									// make sure they don't have fuel scoops so they can't accidentally scoop the cargo they drop
									shp.removeEquipment("EQ_FUEL_SCOOPS");

									// override the pilot name, so it's the same as the mission briefing.
									// it might not ever be seen, but it's still worth making it consistent
									shp.setCrew({
										name: missData.name
									});

									// 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");
									shp.switchAI("oolite-nullAI.js");
									shp.script._savedPrimaryRole = shp.primaryRole;
									shp.script._passcode = expandDescription("[gcm_passcode]");
									shp.desiredSpeed = 0;

									// remove any escorts that came with the ship
									if (shp.escorts) {
										for (var j = shp.escorts.length - 1; j >= 0; j--) {
											shp.escorts[j].remove(true);
										}
									}

									shp.primaryRole = "gcm_contactpoint"; // to avoid pirate attacks

									shp.script._missionID = missData.missionID;
									// add our shipDied event to the shp
									if (shp.script.shipDied) shp.script.$gcm_hold_shipDied = shp.script.shipDied;
									shp.script.shipDied = gcm.$gcm_entity_shipDied;
									// if the ship gets attacked by someone (player or otherwise) include a ship script to tell it to break out of its "silent" mode.
									if (shp.script.shipBeingAttacked) shp.script.$gcm_hold_shipBeingAttacked = shp.script.shipBeingAttacked;
									shp.script.shipBeingAttacked = ms.$gcm_contact_shipBeingAttacked;
									if (shp.script.shipBeingAttackedByCloaked) shp.script.$gcm_hold_shipBeingAttackedByCloaked = shp.script.shipBeingAttackedByCloaked;
									shp.script.shipBeingAttackedByCloaked = ms.$gcm_contact_shipBeingAttackedByCloaked;
									if (shp.script.shipAttackedWithMissile) shp.script.$gcm_hold_shipAttackedWithMissile = shp.script.shipAttackedWithMissile;
									shp.script.shipAttackedWithMissile = ms.$gcm_contact_shipAttackedWithMissile;

									// set up broadcast comms interface
									var bcc = worldScripts.BroadcastCommsMFD;
									if (bcc.$checkMessageExists("gcm_transmit_passcode") === false) {
										bcc.$createMessage({
											messageName: "gcm_transmit_passcode",
											callbackFunction: ms.$transmitPasscode.bind(ms),
											displayText: expandDescription("[gcm_transmit_passcode_player]"),
											messageText: expandDescription("[gcm_transmit_passcode_send]", { code: shp.script._passcode }),
											ship: shp,
											transmissionType: "target",
											deleteOnTransmit: true,
											delayCallback: 5,
											hideOnConditionRed: true
										});
									}

								} else {
									log("galcopBB_meetship", "!!ERROR: Meeting ship not spawned!");
								}
								break;

							case 6:
								if (this._debug) log(this.name, "contact point surprise");
								gns.$createGoonSquad(parseInt((Math.random() * 4) + 3), pos, player.ship.scannerRange * 0.5);
								/*var grp = system.addGroup("pirate", parseInt((Math.random() * 4) + 3), pos, 10000);
								var gn = grp.ships;
								if (gn && gn.length > 0) {
									//var grp = new ShipGroup;
									var pop = worldScripts["oolite-populator"];
									for (var j = 0; j < gn.length; j++) {
										// configure our pirates
										gn[j].setBounty(20 + system.info.government + missData.goons + Math.floor(Math.random() * 8), "setup actions");
										// make sure the pilot has a bounty
										gn[j].setCrew({name:randomName() + " " + randomName(), bounty:gn[j].bounty, insurance:0});
										if (gn[j].hasHyperspaceMotor) {
											pop._setWeapons(gn[j], 1.75); // bigger ones sometimes well-armed
										} else {
											pop._setWeapons(gn[j], 1.3); // rarely well-armed
										}
										// in the safer systems, rarely highly skilled (the skilled ones go elsewhere)
										pop._setSkill(gn[j], 4 - system.info.government);
										if (Math.random() * 16 < system.info.government) {
											pop._setMissiles(gn[j], -1);
										}
										// make sure the AI is switched
										gn[j].switchAI("gcm-pirateAI.js"); 
									}
									gns._goonSquads.push({group:grp, position:pos});
									break;
								}*/
								break;
							default: // disabled, as it's too confusing to the player if there's no notification
								if (this._debug) log("galcopBB_meetship", "contact point surprise 2 - nothing!");
								break;
						}

						// we'll set the waypoint up regardless of the random roll above, so the player won't know what the result is
						gcm.$setWaypoint(pos, [0, 0, 0, 0], "M", expandDescription("[gcm_meeting_point]"), "meeting_" + missData.missionID);

					}.bind(this),
					location: "INNER_SYSTEM",
					locationSeed: list[i].ID
				});
				if (this._checkPlayerNearbyTimer == null || this._checkPlayerNearbyTimer.isRunning === false) {
					this._checkPlayerNearbyTimer = new Timer(this, this.$isPlayerNearby, 5, 5);
				}
			}

			// *** type 32 - fly to waypoint, meet ship deliver data package
			if (list[i].data.missionType === 32 &&
				list[i].destination === system.ID &&
				list[i].data.quantity === 0 &&
				list[i].data.targetQuantity > 0 &&
				list[i].data.destroyedQuantity === 0 &&
				list[i].expiry > clock.adjustedSeconds) {

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

				// add ship with populator
				system.setPopulator("gcm-deliver-data-package-" + list[i].ID, {
					callback: function (pos) {
						var ms = worldScripts.GalCopBB_MeetShip;
						var missData = ms.$getMissionData(32);
						var gcm = worldScripts.GalCopBB_Missions;
						var shp = null;
						var checkShips = null;
						for (var j = 1; j <= 5; j++) {
							checkShips = system.addShips("[" + gcm.$getRandomShipKey(parseInt(missData.missionID), 0) + "]", 1, pos, 3000);
							if (checkShips) shp = checkShips[0];
							if (shp) break;
						}
						if (shp) {
							if (gcm._rsnInstalled) shp.shipUniqueName = gcm.$getRandomShipName(shp, "trader");
							shp.bounty = 0;

							// 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");
							shp.switchAI("oolite-nullAI.js");
							shp.script._savedPrimaryRole = shp.primaryRole;
							shp.primaryRole = "gcm_deliverypoint"; // to avoid pirate attacks
							shp.desiredSpeed = 0;

							// remove any escorts that came with the ship
							if (shp.escorts) {
								for (var j = shp.escorts.length - 1; j >= 0; j--) {
									shp.escorts[j].remove(true);
								}
							}

							shp.script._missionID = missData.missionID;
							// add our shipDied event to the shp
							if (shp.script.shipDied) shp.script.$gcm_hold_shipDied = shp.script.shipDied;
							shp.script.shipDied = gcm.$gcm_entity_shipDied;
							if (shp.script.shipBeingAttacked) shp.script.$gcm_hold_shipBeingAttacked = shp.script.shipBeingAttacked;
							shp.script.shipBeingAttacked = ms.$gcm_contact_shipBeingAttacked;
							if (shp.script.shipBeingAttackedByCloaked) shp.script.$gcm_hold_shipBeingAttackedByCloaked = shp.script.shipBeingAttackedByCloaked;
							shp.script.shipBeingAttackedByCloaked = ms.$gcm_contact_shipBeingAttackedByCloaked;
							if (shp.script.shipAttackedWithMissile) shp.script.$gcm_hold_shipAttackedWithMissile = shp.script.shipAttackedWithMissile;
							shp.script.shipAttackedWithMissile = ms.$gcm_contact_shipAttackedWithMissile;

							// set up broadcast comms interface
							var bcc = worldScripts.BroadcastCommsMFD;
							if (bcc.$checkMessageExists("gcm_transmit_datapackage") === false) {
								bcc.$createMessage({
									messageName: "gcm_transmit_datapackage",
									callbackFunction: ms.$transmitDataPackage.bind(ms),
									displayText: expandDescription("[gcm_transmit_data]"),
									messageText: expandDescription("[gcm_transmit_data_standby]"),
									ship: shp,
									transmissionType: "target",
									deleteOnTransmit: true,
									delayCallback: 5,
									hideOnConditionRed: true
								});
							}
							gcm.$setWaypoint(pos, [0, 0, 0, 0], "M", expandDescription("[gcm_meeting_point]"), "meeting_" + missData.missionID);
						} else {
							log("galcopBB_meetship", "!!ERROR: Data package ship not spawned!");
						}
					}.bind(this),
					location: "INNER_SYSTEM",
					locationSeed: list[i].ID
				});
				if (this._checkPlayerNearbyTimer == null || this._checkPlayerNearbyTimer.isRunning === false) {
					this._checkPlayerNearbyTimer = new Timer(this, this.$isPlayerNearby, 5, 5);
				}
			}

		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// 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 (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;
}

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

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

//-------------------------------------------------------------------------------------------------------------
this.$stopTimers = function $stopTimers() {
	if (this._checkPlayerNearbyTimer && this._checkPlayerNearbyTimer.isRunning) this._checkPlayerNearbyTimer.stop();
	delete this._checkPlayerNearbyTimer;
	if (this._deliveryPointTimer && this._deliveryPointTimer.isRunning) this._deliveryPointTimer.stop();
	delete this._deliveryPointTimer;
	if (this._contactPointTimer && this._contactPointTimer.isRunning) this._contactPointTimer.stop();
	delete this._contactPointTimer;
}

//-------------------------------------------------------------------------------------------------------------
// attached to meeting ships, designed to handle what happens if the ship is attacked
this.$gcm_contact_shipBeingAttacked = function $gcm_contact_shipBeingAttacked(whom) {
	if (this.ship.script.$gcm_hold_shipBeingAttacked) this.ship.script.$gcm_hold_shipBeingAttacked(whom);

	worldScripts.GalCopBB_MeetShip.$contactShipAttacked(this.ship, whom);

	// remove this script so it doesn't keep running
	delete this.ship.script.shipBeingAttacked;
	// restore the original script (if there was one)
	if (this.ship.script.$gcm_hold_shipBeingAttacked) {
		this.ship.script.shipBeingAttacked = this.ship.script.$gcm_hold_shipBeingAttacked;
		delete this.ship.script.$gcm_hold_shipBeingAttacked;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$gcm_contact_shipBeingAttackedByCloaked = function $gcm_contact_shipBeingAttackedByCloaked() {
	if (this.ship.script.$gcm_hold_shipBeingAttackedByCloaked) this.ship.script.$gcm_hold_shipBeingAttackedByCloaked();

	worldScripts.GalCopBB_MeetShip.$contactShipAttacked(this.ship);

	// remove this script so it doesn't keep running
	delete this.ship.script.shipBeingAttackedByCloaked;
	// restore the original script (if there was one)
	if (this.ship.script.$gcm_hold_shipBeingAttackedByCloaked) {
		this.ship.script.shipBeingAttackedByCloaked = this.ship.script.$gcm_hold_shipBeingAttackedByCloaked;
		delete this.ship.script.$gcm_hold_shipBeingAttackedByCloaked;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$gcm_contact_shipAttackedWithMissile = function $gcm_contact_shipAttackedWithMissile(missile, whom) {
	if (this.ship.script.$gcm_hold_shipAttackedWithMissile) this.ship.script.$gcm_hold_shipAttackedWithMissile(missile, whom);

	worldScripts.GalCopBB_MeetShip.$contactShipAttacked(this.ship, whom);

	// remove this script so it doesn't keep running
	delete this.ship.script.shipAttackedWithMissile;
	// restore the original script (if there was one)
	if (this.ship.script.$gcm_hold_shipAttackedWithMissile) {
		this.ship.script.shipAttackedWithMissile = this.ship.script.$gcm_hold_shipAttackedWithMissile;
		delete this.ship.script.$gcm_hold_shipAttackedWithMissile;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$contactShipAttacked = function $contactShipAttacked(ship, whom) {
	ship.commsMessage(expandDescription("[gcm_contact_attacked]"), player.ship);

	var bb = worldScripts.BulletinBoardSystem;
	var missID = ship.script._missionID;
	if (missID > 0) {
		var item = bb.$getItem(missID); // this._dataCache.script._missionID
		item.data.targetQuantity = 0;

		// remove the broadcast comms message - this mission is now a bust
		var w = worldScripts.BroadcastCommsMFD;
		w.$removeMessage("gcm_transmit_passcode");

		if (ship.AIScript.name === "Null AI") ship.switchAI("oolite-traderAI.js");
		ship.target = whom;

		// turn off any pending responses
		var g = worldScripts.GalCopBB_Missions_MFD;
		if (g._subMessageTimer && g._subMessageTimer.isRunning) g._subMessageTimer.stop();
		if (g._offerTimer && g._offerTimer.isRunning) g.$declineNewMission();
	}
	// get the ships response
	if (whom) {
		ship.target = whom;
		ship.performAttack();
	}
	this.ship.AIScript.oolite_priorityai.reconsiderNow();
}

//-------------------------------------------------------------------------------------------------------------
// response after player has transmitted passcode to a contact vessel (via BroadcastCommsMFD)
this.$transmitPasscode = function $transmitPasscode() {
	var targets = system.shipsWithPrimaryRole("gcm_contactpoint");
	for (var i = 0; i < targets.length; i++) {
		if (player.ship.position.distanceTo(targets[i]) < player.ship.scannerRange) {
			worldScripts.GalCopBB_Missions.$unsetWaypoint("meeting_" + targets[i].script._missionID)

			var bcc = worldScripts.BroadcastCommsMFD;
			if (bcc.$checkMessageExists("gcm_player_arrived_data") === true) bcc.$removeMessage("gcm_player_arrived_data");

			targets[i].commsMessage(expandDescription("[gcm_transmit_passcode]"), player.ship);

			// start a timer to control data transfer to player
			this._contactPoint = targets[i];
			this._contactPointTimer = new Timer(this, this.$contactPointComplete.bind(this), 10, 0);
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// completes the meet ship mission, and possibly sets up secondary mission
this.$contactPointComplete = function $contactPointComplete() {
	if (this._contactPoint.isInSpace) {
		if (player.ship.position.distanceTo(this._contactPoint) > player.ship.scannerRange) {
			// set up broadcast comms interface again
			var bcc = worldScripts.BroadcastCommsMFD;
			if (bcc.$checkMessageExists("gcm_transmit_passcode") === false) {
				bcc.$createMessage({
					messageName: "gcm_transmit_passcode",
					callbackFunction: this.$transmitPasscode.bind(this),
					displayText: expandDescription("[gcm_transmit_passcode_player]"),
					messageText: expandDescription("[gcm_transmit_passcode_send]", { code: this._contactPoint.script._passcode }),
					ship: this._contactPoint,
					transmissionType: "target",
					deleteOnTransmit: true,
					delayCallback: 5,
					hideOnConditionRed: true
				});
			}
			return;
		}

		var bb = worldScripts.BulletinBoardSystem;
		var gcm = worldScripts.GalCopBB_Missions;
		this._contactPoint.commsMessage(expandDescription("[gcm_passcode_success]"), player.ship);
		var missID = this._contactPoint.script._missionID;

		var item = bb.$getItem(missID); // this._dataCache.script._missionID
		item.data.quantity = 1;

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

		player.setPlayerRole("trader-courier+");

		this._commsNPC = this._contactPoint;

		var id = -1
		var counter = 0;
		while (id == -1) {
			id = gcm.$createSecondaryMission(missID, true);
			counter += 1;
			// try 10 times to get a secondary
			if (counter == 10) break;
		}
		if (id !== -1) {
			// we've got a new (pending) secondary mission
			// wait for response from player
			gcm._pendingMissionCallback = this.$contactPointFree.bind(this);
			gcm._pendingMissionOrigID = missID;
		} else {
			// give the player some reason to have called them out this far
			this._contactPoint.commsMessage(expandDescription("[gcm_no_mission]"), player.ship);
			// no mission, so just free the ship to go on its way
			this.$contactPointFree();
		}
		// the mission can now be completed at this point - no earlier
		// because the completion type could be "IMMEDIATE", if we do this too early, the mission will disappear from the BB
		// and then all the chaining info is gone.
		bb.$updateBBMissionPercentage(missID, 1);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$contactPointFree = function $contactPointFree() {
	// contact is free now - revert to stored values and let them go
	this._contactPoint.primaryRole = this._contactPoint.script._savedPrimaryRole;

	this._contactPoint.switchAI("oolite-traderAI.js");
	// remove any connection to this mission (so if they're attacked by someone there won't be any lingering mission links)
	this._contactPoint.script._missionID = 0;

	this._commsNPC = null;
	this._contactPoint = null;
	worldScripts.GalCopBB_Missions._pendingMissionCallback = null;
}

//-------------------------------------------------------------------------------------------------------------
// response after player has started to transmit data package to target ship (via BroadcastCommsMFD)
this.$transmitDataPackage = function $transmitDataPackage() {
	var targets = system.shipsWithPrimaryRole("gcm_deliverypoint");
	for (var i = 0; i < targets.length; i++) {
		if (player.ship.position.distanceTo(targets[i]) < player.ship.scannerRange) {
			targets[i].commsMessage(expandDescription("[gcm_transmit_datapackage]"), player.ship);

			// start a timer to control data transfer to ship
			this._deliveryPoint = targets[i];
			this._dataDelivery = 0;
			this._deliveryPointTimer = new Timer(this, this.$deliveryPointTransfer.bind(this), 2, 2);
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// data package transfer process
this.$deliveryPointTransfer = function $deliveryPointTransfer() {
	// make sure the delivery point ship is still valid and in space
	if (this._deliveryPoint.isValid === false || this._deliveryPoint.isInSpace === false) {
		this._deliveryPointTimer.stop()
		return;
	}

	// make sure we can still see the ship
	if (player.ship.position.distanceTo(this._deliveryPoint) > player.ship.scannerRange) {
		// add the broadcast comms message back into the list
		var w = worldScripts.BroadcastCommsMFD;
		if (w.$checkMessageExists("gcm_transmit_datapackage") === false) {
			w.$createMessage({
				messageName: "gcm_transmit_datapackage",
				callbackFunction: this.$transmitDataPackage.bind(this),
				displayText: expandDescription("[gcm_transmit_data]"),
				messageText: expandDescription("[gcm_transmit_data_standby]"),
				ship: this._deliveryPoint,
				transmissionType: "target",
				deleteOnTransmit: true,
				delayCallback: 5
			});
		}
		return;
	}

	this._dataDelivery += 10;
	player.consoleMessage(this._dataDelivery + "\% complete", 1);

	if (this._dataDelivery >= 100) {
		this._deliveryPointTimer.stop();
		if (this._deliveryPoint.isInSpace) {
			this._deliveryPoint.commsMessage(expandDescription("[gcm_delivery_success]"), player.ship);
			var missID = this._deliveryPoint.script._missionID;

			var bb = worldScripts.BulletinBoardSystem;
			var gcm = worldScripts.GalCopBB_Missions;
			var item = bb.$getItem(missID); // this._dataCache.script._missionID
			item.data.quantity = 1;

			// the mission can now be completed 
			bb.$updateBBMissionPercentage(missID, 1);

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

			player.setPlayerRole("trader-courier+");

			this._commsNPC = this._deliveryPoint;
			var id = gcm.$createSecondaryMission(missID, true);

			// contact is free now - revert to stored values and let them go
			this._deliveryPoint.primaryRole = this._deliveryPoint.script._savedPrimaryRole;
			this._deliveryPoint.switchAI("oolite-traderAI.js");
			// remove any connection to this mission (so if they're attacked by someone there won't be any lingering mission links)
			this._deliveryPoint.script._missionID = 0;

			this._commsNPC = null;
			this._deliveryPoint = null;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$isPlayerNearby = function $isPlayerNearby() {
	// don't run this check if the player is busy
	if (player.alertCondition === 3 || player.alertHostiles === true) return;
	// get all powered ships in range
	var ships = player.ship.checkScanner(true);
	var missTypes = [30, 32];
	for (var i = 0; i < ships.length; i++) {
		if (ships[i].script.hasOwnProperty("_missionID") === true && ships[i].hasRole("gcm_delivery_ship") === true) {
			var item = worldScripts.BulletinBoardSystem.$getItem(ships[i].script._missionID);
			if (item && missTypes.indexOf(item.data.missionType) >= 0) {
				if (ships[i].script.hasOwnProperty("_greeted") === false) {
					ships[i].script._greeted = true;
					var bcc = worldScripts.BroadcastCommsMFD;
					// transmit message
					ships[i].commsMessage(expandDescription("[gcm_meeting_question]"), player.ship);
					if (bcc.$checkMessageExists("gcm_player_arrived_data") === false) {
						bcc.$createMessage({
							messageName: "gcm_player_arrived_data",
							callbackFunction: this.$transmitNoResponse.bind(this),
							displayText: expandDescription("[gcm_greet_ship]"),
							messageText: expandDescription("[gcm_player_arrived_data]"),
							ship: ships[i],
							transmissionType: "target",
							deleteOnTransmit: true,
							hideOnConditionRed: true
						});
					}
					bcc.$addShipToArray(ships[i], bcc._greeted);
					bcc.$buildMessageList();
				}
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$transmitNoResponse = function $transmitNoResponse() {
	// this function intentionally left blank
}

//-------------------------------------------------------------------------------------------------------------
this.$acceptedMission = function $acceptedMission(missID) {
	var bb = worldScripts.BulletinBoardSystem;
	var item = bb.$getItem(missID);
	var gcm = worldScripts.GalCopBB_Missions;

	if (this._debug) log(this.name, "accepted mission id = " + missID);

	if (!item) {
		log(this.name, "!!ERROR: BB returned null value from $getItem on mission ID " + missID);
		return;
	}
	gcm.$updateLastMissionDate(item.source, item.data.missionType);


}

//-------------------------------------------------------------------------------------------------------------
this.$completedMission = function $completedMission(missID) {
	var p = player.ship;
	var bb = worldScripts.BulletinBoardSystem;
	var item = bb.$getItem(missID);
	var gcm = worldScripts.GalCopBB_Missions;
	var sbm = worldScripts.Smugglers_BlackMarket;

	// update mission history
	gcm.$updateSuccessHistoryReputation(item);

	// remove any data-type black market sales
	if (item.data.missionType === 32) {
		if (sbm) sbm.$removeSaleItem("DTA_DATA_DELiVERY:" + missID);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$confirmCompleted = function $confirmCompleted(missID) {
	var p = player.ship;
	var result = "";
	var bb = worldScripts.BulletinBoardSystem;
	var item = bb.$getItem(missID);
	if (item) {

	}
	return result;
}

//-------------------------------------------------------------------------------------------------------------
this.$terminateMission = function $terminateMission(missID) {
	var bb = worldScripts.BulletinBoardSystem;
	var item = bb.$getItem(missID);
	var sbm = worldScripts.Smugglers_BlackMarket;
	var gcm = worldScripts.GalCopBB_Missions;

	// adjust reputation only when the terminatePenalty flag is set to true 
	if (item.data.terminatePenalty === true) {
		// update mission history
		gcm.$updateFailedHistoryReputation(item);
	}
	// remove any data-type black market sales
	if (item.data.missionType === 32) {
		if (sbm) sbm.$removeSaleItem("DTA_DATA_DELIVERY:" + missID);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$failedMission = function $failedMission(missID) {
	var bb = worldScripts.BulletinBoardSystem;
	var sbm = worldScripts.Smugglers_BlackMarket;
	var gcm = worldScripts.GalCopBB_Missions;
	var eq = "";

	if (!sbm) {
		// if there's no blackmarket option, just remove the equipment
		this.$terminateMission(missID);
		return;
	}

	var item = bb.$getItem(missID);
	// update mission history
	gcm.$updateFailedHistoryReputation(item);

	if (item.data.missionType === 32 && item.data.quantity === 0 && item.data.targetQuantity > 0) eq = "DTA_DATA_DELIVERY";

	if (eq != "") gcm._equipmentFromFailedMissions.push({
		missionType: item.data.missionType,
		source: item.source,
		equip: eq,
		date: clock.adjustedSeconds
	});
}

//-------------------------------------------------------------------------------------------------------------
this.$updateManifestEntry = function $updateManifestEntry(missID) {
	var gcm = worldScripts.GalCopBB_Missions;
	gcm.$updateManifestEntry(missID);
}

//-------------------------------------------------------------------------------------------------------------
this.$missionAvailability = function $missionAvailability(missID, missType, origSysID) {
	return "";
}

//-------------------------------------------------------------------------------------------------------------
// 30 - meet ship
this.$missionType30_Values = function $missionType30_Values(workTime, routeTime, routeDistance, destSysInfo) {
	var result = {};
	result["quantity"] = 1;
	result["price"] = parseInt((parseInt(Math.random() * 40) + 20) / 10) * 10 + (7 - destSysInfo.government) * 20 +
		worldScripts.GalCopBB_CoreMissionValues.$calcPlayerBonus(200) // plus a possible bonus price, based on player score 
		+
		worldScripts.GalCopBB_CoreMissionValues.$calcDistanceBonus(routeDistance, 20); // plus a distance bonus
	result["expiry"] = clock.adjustedSeconds + routeTime + workTime; // transit time + 1 hour to complete
	result["penalty"] = 0;
	return result;
}

//-------------------------------------------------------------------------------------------------------------
// 32 - deliver data to ship
this.$missionType32_Values = function $missionType32_Values(workTime, routeTime, routeDistance, destSysInfo) {
	var result = {};
	result["quantity"] = 1;
	result["price"] = parseInt((parseInt(Math.random() * 40) + 20) / 10) * 10 + (7 - destSysInfo.government) * 20 +
		worldScripts.GalCopBB_CoreMissionValues.$calcPlayerBonus(200) // plus a possible bonus price, based on player score 
		+
		worldScripts.GalCopBB_CoreMissionValues.$calcDistanceBonus(routeDistance, 20); // plus a distance bonus
	result["expiry"] = clock.adjustedSeconds + routeTime + workTime; // transit time + 1 hour to complete
	result["penalty"] = parseInt(result.price / 2);
	return result;
}