using UnityEngine;


public abstract class Decoder {

	public static string decode(DeployedUnit unit, string order) {
		char[] space = { ' ' };
		string[] split = order.Split(space);//order.ToLower().Trim().Split(space);

		if (split[0] == "fire") {
			return decodeFire(unit, split);
		}
		else if (split[0] == "launch") {
			return decodeLaunch(unit, split);
		}
		else if (split[0] == "prepare") {
			return decodePrepare(unit, split);
		}
		else if (split[0] == "takeoff") {
			return decodeTakeOff(unit, split);
		}
		else if (split[0] == "land") {
			return decodeLand(unit, split);
		}
		else if (split[0] == "set") {
			if (split.Length == 1) {
				return "Unknown set command";
			}
			else if (split[1] == "speed") {
				return decodeSetSpeed(unit, split);
			}
			else if (split[1] == "altitude") {
				return decodeSetAltitude(unit, split);
			}
			return "Unknown set command";
		}

		return order;
	}

	private static string decodeFire(DeployedUnit unit, string[] array) {
		if (array.Length == 1) {
			return "Fire what Sir ?";
		}

		string first = array[1];

		string name = "";
		int number = 1;
		if (int.TryParse(first, out number)) {
			if (array.Length < 3) {
				return "Can you specify what we have to fire Admiral ?";
			}

			name = array[2];
		}
		else {
			number = 1;
			name = array[1];
		}
			
		Class unitClass = GameController.classFromUniqueName(name);

		if (unitClass == null) {
			return "The name of the missile could not be found";
		}

		if (unit.canFire(unitClass, number, unit.getTarget())) {
			unit.fire(unitClass, number, unit.getTarget());
			return "The " + number + " " + unitClass.getName() + " will be fired ASAP !";
		}
		else {
			return "FAIL";
		}
	}

	private static string decodeLaunch(DeployedUnit unit, string[] array) {

		string name = array[2];
		int number = 1;

		int.TryParse(array[1], out number);

		Class unitClass = GameController.classFromUniqueName(name);

		Loadout loadout = unitClass.getLoadout(array[4]);

		if (unit.canLaunch(unitClass, number, loadout)) {
			//unit.prepare(unitClass, number, loadout, true); //no request here
			return "The " + number + " " + unitClass.getName() + " will be launched ASAP !";
		}
		else {
			return "FAIL";
		}
	}

	private static string decodePrepare(DeployedUnit unit, string[] array) {

		string name = array[2];
		int number = 1;

		int.TryParse(array[1], out number);

		Class unitClass = GameController.classFromUniqueName(name);

		Loadout loadout = unitClass.getLoadout(array[4]);

		if (unit.canPrepare(unitClass, number, loadout)) {
			unit.prepare(unitClass, number, loadout); //no request here
			return "The " + number + " " + unitClass.getName() + " will be prepared ASAP !";
		}
		else {
			return "FAIL";
		}
	}

	private static string decodeTakeOff(DeployedUnit unit, string[] array) {
		int id = 1;
		int.TryParse(array[1], out id);

		StoredUnit stored = GameController.storedFromID(id);

		if (stored == null || unit.canTakeOff(stored)) {
			unit.takeOff(stored);
			return "Taking off Sir !";
		}
		else {
			return "FAIL";
		}
	}

	private static string decodeLand(DeployedUnit unit, string[] array) {
		//maybe later, keep a list of units that will land soon, so that the hangars cannot overflow
		if (unit.canLand()) {
			unit.landOn(unit.getMotherShip());
			return "We will land ASAP Sir !";
		}
		else {
			return "FAIL";
		}
	}

	private static string decodeSetSpeed(DeployedUnit unit, string[] array) {
		if (array.Length != 3) {
			return "Invalid set speed command";
		}

		float newSpeed = float.Parse(array[2]);

		if (newSpeed >= unit.getMinSpeed() && newSpeed <= unit.getMaxSpeed()) {
			Requests.setTargetSpeed(unit, newSpeed);
			return "New speed set !";
		}
		else {
			return "The new speed is invalid";
		}
	}

	private static string decodeSetAltitude(DeployedUnit unit, string[] array) {
		if (array.Length != 3) {
			return "Invalid set speed command";
		}

		float newAltitude = float.Parse(array[2]);

		if (newAltitude >= unit.getMinAltitude() && newAltitude <= unit.getMaxAltitude()) {
			Requests.setAltitude(unit, newAltitude);
			return "New altitude set !";
		}
		else {
			return "The new altitude is invalid";
		}
	}
}
