// Porting gcset 11_05.cc to javascript

// Ship constructors
function shipGenericCruiser(){
	this.armour = 10000;
	this.engine = 1500;
	this.weapons = 600;
	this.reactor = 2000;
	this.bridge = 150;
	return this;
}

function Ship(shipConstructor){
//  Constructor for a single Ship
//  Call as, for example: Ship(shipGenericCruiser());
	//alert(shipConstructor.armour + " " + this.armour);

//  Defaults for all ships:
	this.enabled = 1;
	this.armour = 5000;
	this.engine = 750;
	this.weapons = 250;
	this.reactor = 500;
	this.bridge = 25;

//  Get values from ship constructor:
	if(shipConstructor){
		this.armour = shipConstructor.armour;
		//alert(shipConstructor.armour + " " + this.armour);
		this.engine = shipConstructor.engine;
		this.weapons = shipConstructor.weapons;
		this.reactor = shipConstructor.reactor;
		this.bridge = shipConstructor.bridge;
	} else {
		alert("Attempting to create ship w/o constructor!");
	}
//  Set maximum values: 
	this.armour_max = this.armour;
	this.engine_max = this.engine;
	this.weapons_max = this.weapons;
	this.reactor_max = this.reactor;
	this.bridge_max = this.bridge;

	return this;
}


// Each side is an array of up to five ships
var SIDE_NUM_MAX = 2;
var SIDE_MAX_PER = 5;
var side = new Array(SIDE_NUM_MAX);
side[0] = new Array(SIDE_MAX_PER);
side[1] = new Array(SIDE_MAX_PER);



function sideAddShip(sideID,ship){
	var i = 0;
	while(i < SIDE_MAX_PER){
		if(typeof(side[sideID][i]) == "undefined"){
			side[sideID][i] = ship;
			return side[sideID][i];
		}
		i++;
	}
	return null;
}

function sideInit(sideID){
	var i = 0;
	var n = Math.floor(Math.random() * SIDE_MAX_PER);
	if(isNaN(sideID) || sideID < 0 || sideID >= SIDE_NUM_MAX){
		alert("Bad sideID " + sideID + ", max " + SIDE_NUM_MAX);
		return;
	}
	while(i < n){
		sideAddShip(sideID, new Ship(new shipGenericCruiser()));
		i++;
	}
}

function init_game(){
	sideInit(0);
	sideInit(1);

	// TODO: Start the timers 
	// TODO: Add the UI elements
}

// TODO: Function to notify player of the number of enemy
// and request player's input on whether to engage


function sideNumOn(sideID){
// Get how many targetable ships are on a side
	var i = 0;
	var count = 0;
	if((!isNaN(sideID)) && sideID >= 0 && sideID < SIDE_NUM_MAX){
		while(i < SIDE_MAX_PER){
			if(typeof(side[sideID][i]) != "undefined"){
				if(side[sideID][i].enabled == 1){
					count++;
				}
			}
			i++;
		}
	} else {
		alert("sideNumOn: Bad side: " + sideID);
	}
	return count;
}


function sideAnyOther(sideID){
	// Pick any side other than this one. Used for AI targeting.
	var n = Math.floor(Math.random() * (SIDE_NUM_MAX - 1));
	if(n == sideID){
		n = SIDE_NUM_MAX - 1;
	}
	return n;
}

function sideShipGetNth(sideID, n){
	// Select the nth ship (counts from 0)
	//alert("SideShipGetNth: Looking for " + n + " on side " + sideID);
	for(var i = 0; i < SIDE_MAX_PER; i++){
		if(typeof(side[sideID][i]) != "undefined"){
			if(side[sideID][i].enabled == 1){
				if(n == 0){
				//	alert("Found ship at "
				//	+ sideID + ":" + i);
					return side[sideID][i];
				}
				n--;
			} else {
			//	alert(sideID + ":" + i + " is disabled");
			}
		} else {
		//	alert(sideID + ":" + i + " is undefined");
		}
	}
	return null;
}

function shipAITargetLoc(myShip, enemyShip){
	// Simple: target random location (there are 5 possibilities)
	return Math.floor(Math.random() * 5) + 1;
}

function shipAIGetTarget(mySideID){
	// Function for a ship to select a target

	var theirSideID = sideAnyOther(mySideID);
	var n = sideNumOn(theirSideID);

	if(n > 0){
		// Pick one of their ships and target a location
		var targetShip = sideShipGetNth(theirSideID, Math.floor(Math.random() * n));

		// TODO: Order ship to fire and timeout this function
		//alert("TargetShip typeof is " + typeof(targetShip));
		return targetShip;
	} else {
		//alert("Empty side for id " + sideAnyOther(mySideID));
	}
	// noop is nothing to fire at
	return null;
}





// ****************************** //
/* Battle fuction... The fun part */
// ****************************** //

function locmod(targetShip, loc){
	// Return to to-hit modifier for attacked specific locations
	// Values hard-coded, copied from cc version  
	switch(location){
	case 2: return  6; //locmod = target->engmod;
	case 3: return 16; //locmod = target->reacmod;
	case 4: return 18; //locmod = target->gunmod;
	case 5: return 21; //locmod = target->bridmod;
	default: 
	}
	return 0;	// For attacking "no place in particular"
}

function fire(firingShip, targetShip, location){

// Declaring local variables
 var hits = 0;		// number of unassigned hits on the target ship
 this.starthits = 0;	// total number of hits on the target ship
 this.armourhits = 0;	// Hits assigned to the armour of target ship
 this.enghits = 0;	// Hits assigned to the engines of target ship
 this.reachits = 0;	// Hits assigned to the reactor of target ship
 this.gunhits = 0;	// Hits assigned to the guns of target ship
 this.bridhits = 0;	// Hits assigned to the bridge of target ship
 var dodge = 0;		// dodge ability

 var fsckup = "";	// error messages

 // check input
 if(typeof(firingShip) == "undefined"){
	fsckup += "fire(): Firing ship undefined";
 } else if (firingShip.enabled != 1){
	fsckup += "fire(): Firing ship is disabled!"
 }
	
 if(typeof(targetShip) == "undefined"){
	fsckup += "fire(): target ship undefined";
 } else if (targetShip.enabled != 1){
	fsckup += "fire(): Target ship is disabled!"
 }

 if(fsckup.length > 0){
	alert(fsckup);
 }


 // run the function

 dodge = targetShip.engine / targetShip.engine_max; 

  /* The basic battle algorithm */
  // see gcset.cc file for the closest thing you'll get
  // to an explanation of this mess
 hits = parseInt
( firingShip.weapons * 
  (
    (100.0 - 
      (
        (dodge * 33)
        + (Math.random() * 21
          - Math.random() * 6
          )
        + 4 // TODO: Replace with ship's default mod value
        + locmod(location) * dodge
        + .5
      )
    )
    / 100.0 
  )
  * 1 // TODO: replace with ship's weapmod value
);


 starthits = hits;       // Recording the total number of hits

   // the armour takes a portion of the hits relative to
   // the percent of armour still on the ship
    armourhits = parseInt((targetShip.armour / targetShip.armour_max) * hits);
    hits = (hits - armourhits);

    // the target ship takes 45% of the hits to its engines,
    // or 70% if they were specifically targeted

    enghits = parseInt (((45.0 + ((location == 2)* 25)) / 100.0 ) * hits);
    if(targetShip.engine < enghits) { enghits = targetShip.engine; }
    hits = (hits - enghits);

    // the reactor takes 45% of // the remaining hits or 70% if targeted

    reachits = parseInt (( (45.0 + ((location == 3) * 25)) / 100.0 ) * hits);
    hits = (hits - reachits);

    // the guns take a third of the remaining damage,
    // or 7/12 if they were targeted

    gunhits = parseInt(( (33.3 + ((location == 4) * 25)) / 100.0 ) * hits);
    if(targetShip.weapons < gunhits) { gunhits = targetShip.weapons; }
    hits = (hits - gunhits);

    // the bridge takes 1/6 of the remaining hits, or  5/12(was 55%) if targeted.

    bridhits = parseInt (( (16.6 + ((location == 5) * 25)) / 100.0 ) * hits);
    if(targetShip.bridge < bridhits) { bridhits = targetShip.bridge; }
    hits = (hits - bridhits);

 // If any damage was doled out, all remaining damage goes to the armour.
 if (starthits != hits){
  armourhits = (armourhits + hits);
 }
 targetShip.armour -= armourhits;
 targetShip.engine -= enghits;
 targetShip.reactor -= reachits;
 targetShip.weapons -= gunhits;
 targetShip.bridge -= bridhits;
/*
if(targetShip == side[1][0] && targetShip.armour < 4000){
alert("a: " + targetShip.armour
+ "\ne: " + targetShip.engine
+ "\nr: " + targetShip.reactor
+ "\nw: " + targetShip.weapons
+ "\nb: " + targetShip.bridge
+ "\nrhits: " + reachits
+ "\nahits: " + armourhits
+ "\nloc:" + location
);
}
*/

 // Check for destroyed ships
 // Repair any sub-zero non-crits to values of 2
 if (targetShip.reactor < 1         // If target's reactor is less than 1
     //|| targetShip.bridge < 1       // or its bridge
     || targetShip.armour < 1){     // or its armour
    itsdead(targetShip);            // <--
 }
 if (targetShip.engine < 1){ targetShip.engine = 2; }
 if (targetShip.weapons < 1){ targetShip.weapons = 2; }
 if (targetShip.bridge < 1){ targetShip.bridge = 2; }


 // Return hits information for damage report
 return this;
}



function itsdead(targetShip){
	targetShip.enabled = 0;
	targetShip.armour = 0;
	targetShip.engine = 0;
	targetShip.bridge = 0;
	targetShip.reactor = 0;
	targetShip.weapons = 0;
}
