/*
 * common.js
 * Provides common functions and definitions for army lists.
 */

/** Returns translated texts for unit.js
 */
function i18n(text) {
  var currentLanguage = "translatedLanguage";

  if( currentLanguage == "German" ) {
    if( text == "points" )
      return "Punkte";
    else if( text == "lords" )
      return "Kommandanten";
    else if( text == "heroes" )
      return "Helden";
    else if( text == "core" )
      return "Kern";
    else if( text == "special" )
      return "Elite";
    else if( text == "rare" )
      return "Selten";
    else if( text == "Add new unit" )
      return "Neue Einheit hinzufügen";
    else if( text == "Add sub unit" )
      return "Neue Untereinheit hinzufügen";
  }
  return text;
}


// Function to sort items by points value
function pointsSort(a, b) {
	return (b[2] - a[2]);
}

/**
 * Returns a variant of an options array that is sorted and only contains unique items.
 * The first encountered item is kept.
 * @arg As an optional argument a maximum value of the options can ge given.
 */
Array.prototype.optSort = function() {
  // note: array.uniq is not supported everywhere.
  
  // -- unique
  var res = [];
  var l = this.length;

  o: for (var i = 0; i < l; i++) {
      for (var j = res.length-1; j >= 0; j--) {
         if (res[j][0] == this[i][0])
           continue o;
      }

      if( arguments.length > 0 && this[i][2] > arguments[0] )
        continue o;

      res.push(this[i]);
  }

  // -- sort
  return res.sort(pointsSort);
};

/**
 * Returns a variant of an options array that has the specified option added to all
 * sub-options
 * Note: Unless I implement deep copy also the original array is modified.
 */
Array.prototype.optAdd = function(key, value) {
  // -- unique
  var res = this;
  var l = res.length;

  o: for (var i = 0; i < l; i++) {
      if (!res[i][3])
        res[i][3] = {};

      res[i][3][key] = value;
  }

  return res;
};

/** Helper function to set an option for a unit and in the unit's html representation */
function setUnitOption(unit, optionName, count) {
  unit.options[optionName] = count;
  $(unit.getId() + '_' + optionName).checked = (count > 0);
}

/** Helper function to disable or enable a unit option */
function setUnitOptionDisabled(unit, optionName, disabled) {

  $(unit.getId() + '_' + optionName).disabled = disabled;

  if (disabled)
    $('label' + unit.getId() + '_' + optionName).addClassName("disabled");
  else
    $('label' + unit.getId() + '_' + optionName).removeClassName("disabled");

  if (disabled)
    setUnitOption(unit, optionName, 0);
}

/** Ensures that a unit only has "one of" a particular option
    This function is deprecated in favor of the oneOf option
*/
function maxOneOf(unit, optionName, count, changeFunc) {
	if (count == 0) {
		return;
	}
	
	// Go through all the options in a group and deselect others
	unit.forAllSelectedOptions(
		function(option, count) { 
			var optionOptions = option[3];
			if (optionOptions && optionOptions.changeFunction == changeFunc && option[0] != optionName) {
        setUnitOption(unit, option[0], 0);
			}
		});
}

/* The banner mechanism works like this:
   The standard bearer gets a changedFunction: deselectBanners which will
   uncheck all banner options if the standard bearer is deselected.

   The banners will have a disabled: noStandardBearer function disabling
   them.
*/

function noStandardBearer(unit) {
  return !(unit.options.Std || unit.options.iBSB);
}

/** Deselect and disable all options that have the disabled:noStandardBearer set
*/
function deselectBanners(unit, optionName, count) {

	unit.forAllOptions(
		function(option, count2) { 
			var optionOptions = option[3];

			if (optionOptions && optionOptions.disabled == noStandardBearer) {
        setUnitOptionDisabled(unit, option[0], (count == 0));
			}
		});
}

function noChampion(unit) {
	var unitStruct = unit.definition;

  if (unitStruct.maxsize == 1) // single model is always it's own Champ
    return false;

  return !(unit.options.Champ);
}

/** Deselect all magic item options if not selected
*/
function deselectMagic(unit, optionName, count) {
	unit.forAllOptions(
		function(option, count2) { 
			var optionOptions = option[3];

			if (optionOptions && optionOptions.disabled == noChampion) {
        setUnitOptionDisabled(unit, option[0], (count == 0));
			}
		});
    
	if (count > 0) {
		return;
	}
}

/**
 *  A deployment function gets a unit and fills the given map with arrays.
 *  Usually this function should add icons at the give positions.
 *
 *  @param unit The unit for which the positions array should be filled out.
 *  @param positions A map containing front, middle, back, bottom, top, left, right
 */
function normalDeployment(unit, positions) {

  var unitStruct = unit.definition;
  var unitIcons = unitStruct.icons;

  // Look for some special options (and icons)
  unit.forAllSelectedOptions(
	function(option, count) { 
		var optionOptions = option[3];
		if (optionOptions != null && optionOptions.icons != null) {
			if (option[0].charAt() == 'i' || option[0].charAt() == 'm') {
				unitIcons = optionOptions.icons;
			}
			// Maybe a special addition
			else if (option[0].charAt() == 's') {
				for(var i = 0; i < count; i++) {
					positions.left.push(optionOptions.icons);
				}
			}
		}
	});
	
	if (unit.options.Champ) {
		unit.addOptionIcons(positions.front, 'Champ');
	}
	if ( unit.options.Std) {
		unit.addOptionIcons(positions.front, 'Std');
	}
	if (unit.options.Music) {
		unit.addOptionIcons(positions.front, 'Music');
	}
	
	if (unitIcons) {
		for (var i = 0; i < unit.count - positions.front.length; i++) {
			positions.middle.push(unitIcons);
		}
	}
	
	return positions;
}

/**
 *  Special deployment function that leaves some spaces
 *
 *  @param unit The unit for which the positions array should be filled out.
 *  @param positions A map containing front, middle, back, bottom, top, left, right
 */
function spreadDeployment(unit, positions) {
	normalDeployment(unit, positions);
	
	for (var i = positions.middle.length - 1; i > 0; i -= 2) {
		positions.middle.splice(i, 0, null); // Add some empty spaces in the middle
	}
	
	return positions;
}

// the maxOneOf functions are deprecated
// use oneOf option instead
function maxOneOfBanner( unit, optionName, count ) {
  return maxOneOf( unit, optionName, count, maxOneOfBanner );
}

function maxOneOfArm(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfArm);
}

function maxOneOfMount(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfMount);
}

function maxOneOfWep(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfWep);
}
function maxOneOfMWep(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfMWep);
}

function maxOneOfMount(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfMount);
}

function maxOneOfMEnc(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfMEnc);
}
function maxOneOfMArm(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfMArm);
}
function maxOneOfMArc(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfMArc);
}
function maxOneOfMTalisman(unit, optionName, count) {
	return maxOneOf(unit, optionName, count, maxOneOfMTalisman);
}

var commonLores = [
	["optLoreFire", "Lore of Fire", 0, {oneOf: "Lore"}],
	["optLoreBeasts", "Lore of Beasts", 0, {oneOf: "Lore"}],
	["optLoreHeavens", "Lore of Heavens", 0, {oneOf: "Lore"}],
	["optLoreMetal", "Lore of Metal", 0, {oneOf: "Lore"}],
	["optLoreLight", "Lore of Light", 0, {oneOf: "Lore"}],
	["optLoreLife", "Lore of Life", 0, {oneOf: "Lore"}],
	["optLoreShadow", "Lore of Shadow", 0, {oneOf: "Lore"}],
	["optLoreDeath", "Lore of Death", 0, {oneOf: "Lore"}]
];

var commonMagicWep = [
	["mBlGiant", "Giant Blade", 60],
	["mSwBlood", "Sword of Bloodshed", 60],
	["mBlObsidian", "Obsidian Blade", 50],
	["mBlOgre", "Ogre Blade", 40],
	["mSwStrife", "Sword of Strife", 40],
	["mBlFencers", "Fencer's Blades", 35],
	["mSwAHeroes", "Sword of Anti-Heroes", 30],
	["mSpellTh", "Spellthieving Sword", 25],
	["mSwSwift", "Sword of Swift Slaying", 25],
	["mSwBattle", "Sword of Battle", 20],
	["mSwBersk", "Berserker Sword", 20],
	["mSwMight", "Sword of Might", 20],
	["mSwGSigil", "Gold Sigil Sword", 15],
	["mSwStrike", "Sword of Striking", 15],
	["mBlBiting", "Biting Blade", 10],
	["mSwRelic", "Relic Sword", 10],
	["mBlShriek", "Shrieking Blade", 10],
	["mSwTorment", "Tormentor Sword", 5],
	["mWarrBane", "Warrior Bane", 5]
];

var commonMagicArm = [
	["mArmDestiny", "Armour of Destiny", 50],
	["mHlmTricksters", "Trickster's Helm", 50],
	["mArmSlvrSteel", "Armour of Silvered Steel", 45],
	["mArmFortune", "Armour of Fortune", 35],
	["mHlmDiscord", "Helm of Discord", 30],
	["mSclGlittering", "Glittering Scales", 25],
	["mShPtolos", "Shield of Ptolos", 25],
	["mShSpell", "Spellshield", 20],
	["mArmGamblers", "Gambler's Armour", 20],
	["mHlmDragon", "Dragonhelm", 10],
	["mShEnchanted", "Enchanted Shield", 5],
	["mShCharmed", "Charmed Shield", 5]
];

var commonMagicEnc = [
	["mWizHat", "Wizarding Hat", 100],
	["mFozzrik", "Fozzrik's Folding Fortress", 100],
	["mArCarpet", "Arabyan Carpet", 50],
	["mCrCmd", "Crown of Command", 35],
	["mHealPot", "Healing Potion", 35],
	["mFthTorc", "Featherfoe Torc", 35],
	["mRubyRing", "Ruby Ring of Ruin", 25],
	["mMaskEee", "The Terrifying Mask of EEE!", 25],
	["mStrPot", "Potion of Strength", 20],
	["mToughPot", "Potion of Toughness", 20],
	["mTrkShrd", "The Other Trickster's Shard", 15],
	["mIroncurse", "Ironcurse Icon", 5],
	["mFoolPot", "Potion of Foolhardiness", 5],
	["mSpeedPot", "Potion of Speed", 5]
];

var commonMagicArc = [
	["mArcAshur", "Book of Ashur", 70],
	["mArcFeedback", "Feedback Scroll", 50],
	["mArcLeeching", "Scroll of Leeching", 50],
	["mArcSivejirs", "Sivejir's Hex Scroll", 50],
	["mArcPower", "Power Scroll", 35],
	["mArcWandJet", "Wand of Jet", 35],
	["mArcForbidden", "Forbidden Rod", 35],
	["mArcTricksters", "Trickster's Shard", 25],
	["mArcEarthing", "Earthing Rod", 25],
	["mArcDispel", "Dispel Scroll", 25],
	["mArcPowerSt", "Power Stone", 25],
	["mArcSceptre", "Sceptre of Stability", 15],
	["mArcChannel", "Channelling Staff", 15],
	["mArcShielding", "Scroll of Shielding", 15]
];

var commonMagicTal = [
	["mTalWard4", "Talisman of Preservation", 45],
	["mTalMRes3", "Obsidian Lodestone", 45],
	["mTalWard5", "Talisman of Endurance", 30],
	["mTalMRes2", "Obsidian Amulet", 30],
	["mTalDawnStone", "Dawnstone", 25],
	["mTalOpal", "Opal Amulet", 15],
	["mTalMRes1", "Obsidian Trinket", 15],
	["mTalWard6", "Talisman of Protection", 15],
	["mTalRegen", "Seed of Rebirth", 10],
	["mTalDrgBane", "Dragonbane Gem", 5],
	["mTalPigeon", "Pidgeon Plucker's Pendant", 5],
	["mTalLuck", "Luckstone", 5]
];

var commonMagicBan = [
	["mStdRampagers", "Rampager's Standard", 55],
	["mStdWailing", "Wailing Banner", 50],
	["mStdRangers", "Ranger's Standard", 50],
	["mStdRazor", "Razor Standard", 45],
	["mStdWar", "War Banner", 35],
	["mStdSwiftness", "Banner of Swiftness", 15],
	["mStdLiche", "Lichebone Pennant", 15],
	["mStdDiscipline", "Standard of Discipline", 15],
	["mStdFlame", "Banner of Eternal Flame", 10],
	["mStdGleaming", "Gleaming Pennant", 5],
	["mStdScarecrow", "Scarecrow Banner", 15]
].optAdd("disabled", noStandardBearer);


