using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using UnityEngine;
using System;

public enum ConsumptionIncrease {Square = 0, Linear = 1};

public class EngineModule : Module {

	private float minSpeed;
	private float maxSpeed;
	private float acceleration;

	private Graph speedDistanceTarget;

	private float angularSpeed;
	private float verticalAngleRange;

	private float cruiseAltitude;
	private float minAltitude;
	private float maxAltitude;

	private FuelType fuelType;
	private float fuelConsumption;
	private ConsumptionIncrease consumptionIncrease;

	public EngineModule(JObject json) : base(json) {
		maxSpeed = (float)json["maxSpeed"];
		acceleration = (float)json["acceleration"];
		angularSpeed = Mathf.Deg2Rad * (float)json["angularSpeed"];

		JToken token;
		if (json.TryGetValue("minSpeed", out token)) {
			minSpeed = (float)json["minSpeed"];
		}
		else {
			minSpeed = 0.0f;
		}

		speedDistanceTarget = new Graph(json, "speedDistanceTarget");

		if (json.TryGetValue("cruiseAltitude", out token)) {
			cruiseAltitude = (float)json["cruiseAltitude"];
		}
		else {
			cruiseAltitude = 0.0f;
		}

		if (json.TryGetValue("minAltitude", out token)) {
			minAltitude = (float)json["minAltitude"];
		}
		else {
			minAltitude = 0.0f;
		}

		if (json.TryGetValue("maxAltitude", out token)) {
			maxAltitude = (float)json["maxAltitude"];
		}
		else {
			maxAltitude = 0.0f;
		}

		if (json.TryGetValue("verticalAngleRange", out token)) {
			verticalAngleRange = Mathf.Deg2Rad * (float)json["verticalAngleRange"];
		}
		else {
			verticalAngleRange = 0.0f;
		}

		fuelType = (FuelType)((int)json["fuelType"] - 1);
		fuelConsumption = (float)json["fuelConsumption"];

		if (json.TryGetValue("consumptionIncrease", out token)) {
			consumptionIncrease = (ConsumptionIncrease)((int)json["consumptionIncrease"] - 1);;
		}
		else {
			consumptionIncrease = ConsumptionIncrease.Linear;
		}

		icon = Resources.Load("Sprites/Modules/Icons/Engines/" + getUniqueName(), typeof(Sprite)) as Sprite;
		silhouette = Resources.Load("Sprites/Modules/Silhouettes/Engines/" + getUniqueName(), typeof(Sprite)) as Sprite;
	}

	public static EngineModule[] loadModules(string[] filenames) {
		Array.Sort(filenames);
		EngineModule[] array = new EngineModule[filenames.Length];

		for (int i = 0; i < filenames.Length; i++) {
			array[i] = new EngineModule(jsonFromFile(filenames[i]));
		}

		return array;
	}

	public float getMaxSpeed(GraphParams param) {
		return maxSpeed * speedDistanceTarget.evaluate(param.distanceTarget);
	}

	public float getMinSpeed() {
		return minSpeed;
	}

	public float getAcceleration() {
		return acceleration;
	}

	public float getAngularSpeed() {
		return angularSpeed;
	}

	public float getVerticalAngleRange() {
		return verticalAngleRange;
	}

	public float getCruiseAltitude() {
		return cruiseAltitude;
	}

	public float getMinAltitude() {
		return minAltitude;
	}

	public float getMaxAltitude() {
		return maxAltitude;
	}

	public FuelType getFuelType() {
		return fuelType;
	}

	public float getFuelConsumption(float ratio) {
		switch (consumptionIncrease) {
			default:
				return ratio * fuelConsumption;
			
			case ConsumptionIncrease.Square:
				return ratio * ratio * fuelConsumption;
		}
	}

	override public void updateClasses() {
	}

	override public ModuleData getData(int parent, float angleOffset, Vector position) {
		return new EngineModuleData(parent, this, position);
	}
}

public class EngineModuleData : ModuleData {
	public EngineModuleData(int parent, Module template, Vector position) : base(parent, template, position) {
	}
}