"use strict";
this.name = "draven_ship_player.js";
this.author = "Ironfist";
this.copyright = "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description = "Ship script for draven player ships";
this.version = "2.1";
// based on scripts from Thargoid for the Vortex

this._hairSpace = String.fromCharCode(31);
this._hairSpaceLength = defaultFont.measureString(this._hairSpace);
this._ellip = "…";

this.allShipNames = expandMissionText("dr_allshipnames").split("|");
this.shipNames = expandMissionText("dr_shipnames").split("|");
this.debug = false;
// General, start and GUI

//-------------------------------------------------------------------------------------------------------------
this.startUp = function () {
	if (this.allShipNames.indexOf(player.ship.name) == -1) return;
	if (this.debug) log(this.name, "Script Name " + this.name);

	if (this.debug) log(this.name, "draven Startup");
	if (player.ship.equipmentStatus("EQ_DRAVEN") !== "EQUIPMENT_OK") {
		player.ship.awardEquipment("EQ_DRAVEN");
	}
	if (player.ship.subEntities.length > 0) {
		if (player.ship.equipmentStatus("EQ_DRAVEN_TURRET") !== "EQUIPMENT_OK") {
			if (this.debug) log(this.name, "draven Set Kit");
			player.ship.awardEquipment("EQ_DRAVEN_SHIP");
			player.ship.awardEquipment("EQ_DRAVEN_TURRET");
		}
		if (this.debug) log(this.name, "draven Player Script Initialised");
		if (this.debug) log(this.name, missionVariables.DRAVEN_TURRET);
		if (missionVariables.DRAVEN_TURRET === null) { 
			missionVariables.DRAVEN_TURRET = "active"; 
		}
		if (this.debug) log(this.name, missionVariables.DRAVEN_TURRET);
	}
	this.incompatibleEquipment = ["EQ_REPAIRBOTS_CONTROLLER", "EQ_MIL_INJECTION"];
	this.oldTarget = "NONE";
}

//-------------------------------------------------------------------------------------------------------------
this.resetdraven = function () {
	missionVariables.DRAVEN_TURRET = null;
	if (this.debug) log(this.name, "draven Reset");
}

//-------------------------------------------------------------------------------------------------------------
this.playerBoughtNewShip = function (ship) {
	this.resetdraven();

	if (this.shipNames.indexOf(player.ship.name) >= 0) { // if we just bought a Draven Gunship
		this.startUp();
		mission.runScreen({ title: expandMissionText("dr_ship_purchase_title", {shipname: player.ship.name}), model: player.ship.dataKey });
		this.AIName = "MAC" + Math.floor((Math.random() * 0.999999) * 10) + Math.floor((Math.random() * 0.999999) * 10) + Math.floor((Math.random() * 0.999999) * 10) + Math.floor((Math.random() * 0.999999) * 10);
		mission.addMessageText(expandMissionText("dr_ship_stats", {shipname:player.ship.name, rego:this.AIName}));
		mission.addMessageText(this.$padText(expandMissionText("dr_col1_title"), 20) + this.$padText(expandMissionText("dr_col2_title"), 11, true));
		mission.addMessageText(this.$padText(expandMissionText("dr_source", {data:player.ship.scriptInfo.draven.infoSource}), 20) + this.$padText(expandMissionText("dr_mil_ai"), 11, true));
		mission.addMessageText(this.$padText(expandMissionText("dr_speed", {speed:player.ship.maxSpeed}), 20) + this.$padText(expandMissionText("dr_auto_repair"), 11, true));
		mission.addMessageText(this.$padText(expandMissionText("dr_cargo", {cap:player.ship.cargoSpaceCapacity}), 20) + this.$padText(expandMissionText("dr_defence"), 11, true));
		mission.addMessageText(this.$padText(expandMissionText("dr_missiles", {num:player.ship.missileCapacity}), 20) + this.$padText(expandMissionText("dr_regen_fi"), 11, true));
		mission.addMessageText(this.$padText(expandMissionText("dr_energy", {num:parseInt(player.ship.maxEnergy / 64)}), 20) + this.$padText(expandMissionText("dr_movement", {pitch:player.ship.maxPitch.toFixed(1), roll:player.ship.maxRoll.toFixed(1), yaw:player.ship.maxYaw.toFixed(1)}), 11, true));
		mission.addMessageText(expandMissionText("dr_ai_greeting", {ainame:this.AIName, shipname:player.ship.name, shipclassname:player.ship.shipClassName}));
	}
}

//-------------------------------------------------------------------------------------------------------------
this.turretToggle = function () {
	if (missionVariables.DRAVEN_TURRET === "active") {
		if (this.debug) log(this.name, "draven turret active " + player.ship + "::" + player.ship.target);
		player.ship.restoreSubEntities();
		if (player.ship && player.ship.target) {
			var subCounter = player.ship.subEntities.length;
			if (this.debug) log(this.name, "Setting guns to target.");
			while (subCounter--) { 
				player.ship.subEntities[subCounter].target = player.ship.target; 
			}
		}
	} else {
		if (this.debug) log(this.name, player.ship + "::" + missionVariables.DRAVEN_TURRET);
		var subCounter = player.ship.subEntities.length;
		while (subCounter--) { 
			player.ship.subEntities[subCounter].remove(); 
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.playerBoughtEquipment = function (equipment) {
	if (this.shipNames.indexOf(player.ship.name) == -1) return;

	if (this.incompatibleEquipment.indexOf(equipment) != -1) {
		mission.runScreen({ title: expandMissionText("dr_incompatible_equip_title")});
		mission.addMessageText(expandMissionText("dr_incompatible_equip", {equip:EquipmentInfo.infoForKey(equipment).name, refund:formatCredits(EquipmentInfo.infoForKey(equipment).price / 10, true, true)}));
		player.credits += EquipmentInfo.infoForKey(equipment).price;
		player.ship.removeEquipment(equipment);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentDamaged = function (equipment) {
	if (this.shipNames.indexOf(player.ship.name) == -1) return;

	if (player.ship.docked) return;

	if (!this.damageControlTimer || !this.damageControlTimer.isRunning) {
		var repairTime = 30 + Math.ceil(Math.random() * player.ship.scriptInfo.draven.repairTime);
		player.consoleMessage(expandMissionText("dr_regen_working"), 6);
		this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedFromStation = function (station) {
	if (this.shipNames.indexOf(player.ship.name) == -1) return;

	this.turretToggle(); // remove turrets if they are de-activated (having been restored on docking to avoid overhaul offer)
	this.startFuelTimer();
	this.startMissileTimer();
	this.repairCheck();
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillDockWithStation = function (station) {
	if (this.shipNames.indexOf(player.ship.name) == -1) return;

	player.ship.restoreSubEntities(); // if the turrets are not on the ship on docking, a maintenance overhaul is offered to restore them!
	this.stopFuelTimer();
	this.stopMissileTimer();

	if (this.damageControlTimer && this.damageControlTimer.isRunning) this.damageControlTimer.stop();

	player.ship.awardEquipment("EQ_RENOVATION");
	player.ship.removeEquipment("EQ_RENOVATION"); // as it's a self-repairing ship, should never need a maintenance overhaul...
}

//-------------------------------------------------------------------------------------------------------------
/*this.guiScreenChanged = function (to, from) {
	if (this.shipNames.indexOf(player.ship.name) == -1) return;

	if (from == "GUI_SCREEN_MARKET") {
		if (this.debug) log(this.name, player.ship.name + "07a");
		player.consoleMessage(" \n \n \n \n \n \n \n \n", 1); // remove the current bay text if we leave the screen
	}

	if (from == "GUI_SCREEN_EQUIP_SHIP") {
		if (this.debug) log(this.name, player.ship.name + "07b");
		player.consoleMessage(" \n \n \n \n \n \n \n \n", 1); // remove the current bay text if we leave the screen
	}

	if (to == "GUI_SCREEN_MARKET") {
		if (from == "GUI_SCREEN_MANIFEST") { // access only from manifest to market
			if (this.debug) log(this.name, player.ship.name + "07c");
		} else {
			if (this.debug) log(this.name, player.ship.name + "07d");
		}
	}
}*/

// Self repair

//-------------------------------------------------------------------------------------------------------------
this.repairCheck = function () {
	this.checkSystems();
	if (this.playerDamagedList.length > 0) {
		var repairTime = 30 + Math.ceil(Math.random() * player.ship.scriptInfo.draven.repairTime);
		player.consoleMessage(expandMissionText("dr_regen_started"), 6);
		this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.checkSystems = function () {
	this.playerDamagedList = [];
	var repairCounter = 0;
	for (repairCounter = 0; repairCounter < player.ship.equipment.length; repairCounter++) {
		var scriptEq = EquipmentInfo.infoForKey(player.ship.equipment[repairCounter].equipmentKey);
		if (player.ship.equipmentStatus(player.ship.equipment[repairCounter].equipmentKey) == "EQUIPMENT_DAMAGED"
			&& ((scriptEq.scriptInfo.IronfistRepairBotChance === undefined
				|| isNaN(scriptEq.scriptInfo.IronfistRepairBotChance))
				|| (!isNaN(scriptEq.scriptInfo.IronfistRepairBotChance)
					&& scriptEq.scriptInfo.IronfistRepairBotChance > 0))
		) { 
			this.playerDamagedList.push(player.ship.equipment[repairCounter].equipmentKey); 
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.repairSystems = function () {
	this.checkSystems();
	if (this.playerDamagedList.length == 0) {
		player.consoleMessage(expandMissionText("dr_regen_complete"), 5);
		return;
	} else {
		var damagedEquipment = Math.floor(Math.random() * this.playerDamagedList.length); // pick a random element from the list...
		this.fixedItem = this.playerDamagedList[damagedEquipment]; // ...define the item...
		this.fixedName = EquipmentInfo.infoForKey(this.fixedItem).name; // define it's screen name
		this.fixedTech = EquipmentInfo.infoForKey(this.fixedItem).effectiveTechLevel // tech level of the item

		switch (true) {
			case (EquipmentInfo.infoForKey(this.fixedItem).scriptInfo.IronfistRepairBotChance !== undefined && !isNaN(EquipmentInfo.infoForKey(this.fixedItem).scriptInfo.IronfistRepairBotChance)):
				this.fixChance = EquipmentInfo.infoForKey(this.fixedItem).scriptInfo.IronfistRepairBotChance; 
				break;
			case (this.fixedTech < 9): 
				this.fixChance = 1; 
				break;
			case ((this.fixedTech > 8) && (this.fixedTech < 17)): 
				this.fixChance = 1 - ((this.fixedTech - 8) / 10); 
				break;
			case (this.fixedTech == 99): 
				this.fixChance = 0.1; 
				break;
			default: 
				this.fixChance = 0.2; 
				break;
		}
	}

	if (Math.random() < this.fixChance) {
		this.fixItem();
	} else {
		var repairTime = 30 + Math.ceil(Math.random() * player.ship.scriptInfo.draven.repairTime);
		player.consoleMessage(expandMissionText("dr_regen_ongoing", {equip:this.fixedName}), 5);
		this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.fixItem = function () {
	player.ship.setEquipmentStatus(this.fixedItem, "EQUIPMENT_OK"); // and actually fix the thing!
	player.consoleMessage(expandMissionText("dr_regen_fixed", {equip:this.fixedName}), 5)
	switch (this.fixedItem) { // specific OXP equipment which need rebooting after fixing, or have other issues.
		case "EQ_FUEL_INJECTION":
			this.startFuelTimer();
			break;
		case "EQ_FRAME_FUEL_COLLECTOR":
			if (worldScripts["Fuel Collector"]) { worldScripts["Fuel Collector"].shipLaunchedFromStation(); }
			break;
		case "EQ_FRAME_BOUNTY_SCANNER":
			if (worldScripts["Bounty Scanner"]) { worldScripts["Bounty Scanner"].shipLaunchedFromStation(); }
			break;
		case "EQ_EEU":
			if (worldScripts["Emergency Energy Unit"]) { worldScripts["Emergency Energy Unit"].shipLaunchedFromStation(); }
			break;
		case "EQ_ROCKHERMIT_SCANNER":
			if (worldScripts["rockHermit_Locator"]) { worldScripts["rockHermit_Locator"].shipLaunchedFromStation(); }
			break;
	}

	if (this.playerDamagedList.length > 1) {
		var repairTime = 30 + Math.ceil(Math.random() * player.ship.scriptInfo.draven.repairTime);
		player.consoleMessage(expandMissionText("dr_regen_more"), 6);
		this.damageControlTimer = new Timer(this, this.repairSystems, repairTime);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.startMissileTimer = function () {
	if (player.ship.docked) return;
	if (this.missileWatchTimer) { 
		this.missileWatchTimer.start(); 
	} else { 
		this.missileWatchTimer = new Timer(this, this.checkMissileBays, 0, 1); 
	}
}

//-------------------------------------------------------------------------------------------------------------
this.stopMissileTimer = function () {
	if (this.missileWatchTimer && this.missileWatchTimer.isRunning) this.missileWatchTimer.stop();
}

//-------------------------------------------------------------------------------------------------------------
this.checkMissileBays = function () {
	if (!player.ship || !player.ship.isValid) {
		this.stopMissileTimer();
		return;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipFiredMissile = function (missile, target) {
	if (this.shipNames.indexOf(player.ship.name) == -1) return;

	if (this.missileWatchTimer && !this.missileWatchTimer.isRunning) {
		this.startMissileTimer();
	}
}

// Defense System

//-------------------------------------------------------------------------------------------------------------
this.shipAttackedWithMissile = function (missile, whom) {
	if (this.shipNames.indexOf(player.ship.name) == -1) return;

	if (missile.scanClass != "CLASS_MISSILE" || (this.defenseTimer && this.defenseTimer.isRunning) || (whom && whom.isPlayer)) return;

	if (missile) {
		this.missileData = missile; 
	} else {
		this.missileData = null; 
	}
	if (whom) {
		this.whomData = whom;
	} else {
		this.whomData = null;
	}
	player.consoleMessage(expandMissionText("dr_defence_activated"), 2);
	this.defenseTimer = new Timer(this, this.defendMissile, 1, 1);
}

//-------------------------------------------------------------------------------------------------------------
this.defendMissile = function () {
	if (!this.missileData || !this.missileData.isValid) {
		this.defenseTimer.stop();
		delete this.defenseTimer;
		this.missileData = null;
		this.whomData = null;
		this.missileScan();
		return;
	}

	if (player.ship.position.distanceTo(this.missileData.position) < 5000) {
		if (player.ship.target && this.oldTarget === "NONE") {
			this.oldTarget = player.ship.target;
		}
		player.ship.target = this.missileData;
	}

	if (player.ship.position.distanceTo(this.missileData.position) < 2500) { // if missile is within 2.5km or so, try ECM'ing it too.
		player.ship.fireECM;
		if (!this.missileData || !this.missileData.isValid) {
			this.defenseTimer.stop();
			delete this.defenseTimer;
			this.missileData = null;
			this.whomData = null;
			this.missileScan();
			return;
		}
	}

	this.defenseChance = Math.random();
	if (this.defenseChance > 0.25 || !this.missileData) return;

	if (this.defenseChance < 0.05 && this.whomData && this.whomData.isValid) {
		this.missileData.target = this.whomData;
	} else {
		this.missileData.target = null;
		this.missileData.reactToAIMessage("TARGET_LOST");
	}
}

//-------------------------------------------------------------------------------------------------------------
this.missileScan = function () {
	function incomingMissiles(entity) { return entity.isMissile && entity.target && entity.target.isPlayer };
	let targetMissiles = system.filteredEntities(this, incomingMissiles, player.ship, 25600);
	if (targetMissiles.length > 0 && !this.defenseTimer) {
		this.missileData = targetMissiles[0];
		player.ship.target = targetMissiles[0];
		this.whomData = null;
		this.defenseTimer = new Timer(this, this.defendMissile, 1, 1);
	} else {
		player.consoleMessage(expandMissionText("dr_defence_deactivated"), 2);
		if (this.oldTarget && this.oldTarget != "NONE" && this.oldTarget.isValid && (player.ship.position.distanceTo(this.oldTarget.position) < 25600) && !player.ship.target) { 
			player.ship.target = this.oldTarget; 
		}
		this.oldTarget = "NONE";
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipBeingAttacked = function (whom) {
	if (this.shipNames.indexOf(player.ship.name) == -1) return;
	if (Math.random() < 0.25 && whom && whom.target && whom.target.isPlayer) {
		whom.target = null;
		whom.reactToAIMessage("TARGET_LOST");
	}

	if (player.ship.energy < 33 && player.ship.fuel > 0) {
		this.xDistance = ((Math.random() * 2) - 1) * 1024000;
		this.yDistance = ((Math.random() * 2) - 1) * 1024000;
		this.zDistance = ((Math.random() * 2) - 1) * 1024000;
		this.newPosition = player.ship.position.add([this.xDistance, this.yDistance, this.zDistance]);

		let probe = player.ship.spawnOne('splinter');
		probe.position = this.newPosition;
		if (probe && probe.isValid) {
			probe.remove();
			player.ship.position = this.newPosition;
			player.ship.fuel -= 0.1;
			player.consoleMessage(expandMissionText("dr_emergency_displacement"), 8);
		}
	}
}

// Military grade fuel injection	

//-------------------------------------------------------------------------------------------------------------
this.startFuelTimer = function () {
	this.fuelFlag = 0;
	if (this.fuelWatchTimer) { 
		this.fuelWatchTimer.start(); 
	} else { 
		this.fuelWatchTimer = new Timer(this, this.checkSpeed, 0, 1); 
	}
}

//-------------------------------------------------------------------------------------------------------------
this.stopFuelTimer = function () {
	this.fuelFlag = 0;
	if (this.fuelWatchTimer && this.fuelWatchTimer.isRunning) this.fuelWatchTimer.stop();
}

//-------------------------------------------------------------------------------------------------------------
this.checkSpeed = function () {
	if (player.ship.equipmentStatus("EQ_FUEL_INJECTION") !== "EQUIPMENT_OK") {
		this.stopFuelTimer();
		return;
	}

	if (player.ship.speed == 7 * player.ship.maxSpeed) { // if the ship is under fuel injection (FI is speed x 7, torus is speed x 32)
		// increment flag, looping between 0 and 9
		this.fuelFlag += 1;
		this.fuelFlag = this.fuelFlag % 8;
	} else 
		return; // if not under fuel injection, exit function

	if (this.fuelFlag == 7) { // every 8th second under fuel injection
		player.ship.fuel += 0.1;
		player.ship.velocity = player.ship.velocity.multiply(1.25);
	}
}

//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padText = function $padText(currentText, desiredLength, leftSwitch, centreSwitch) {
    var that = $padText;
    var hairSpace = (that.hairSpace = that.hairSpace || this._hairSpace);
    var ellip = (that.ellip = that.ellip || this._ellip);
    var hairSpaceLength = (that.hairSpaceLength = that.hairSpaceLength || this._hairSpaceLength);
    var measure = (that.measure = that.measure || defaultFont.measureString);

    if (currentText == null) currentText = "";
    var currentLength = measure(currentText.replace(/%%/g, "%"));
    // calculate number needed to fill remaining length
    var padsNeeded = ~~((desiredLength - currentLength) / hairSpaceLength);
    if (padsNeeded < 1) {
        // text is too long for column, so start pulling characters off
        var tmp = currentText;
        do {
            tmp = tmp.substring(0, tmp.length - 2) + ellip;
            if (tmp === ellip) break;
        } while (measure(tmp.replace(/%%/g, "%")) > desiredLength);
        currentLength = measure(tmp.replace(/%%/g, "%"));
        padsNeeded = ~~((desiredLength - currentLength) / hairSpaceLength);
        currentText = tmp;
    }
    // quick way of generating a repeated string of that number
    if (!leftSwitch || leftSwitch === false) {
        if (!centreSwitch || centreSwitch === false) {
            return currentText + new Array(padsNeeded).join(hairSpace);
        } else {
            return currentText + new Array(parseInt(padsNeeded / 2)).join(hairSpace);
        }
    } else {
        if (!centreSwitch || centreSwitch === false) {
            return new Array(padsNeeded).join(hairSpace) + currentText;
        } else {
            return new Array(parseInt(padsNeeded / 2)).join(hairSpace) + currentText;
        }
    }
}
