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

public enum ClassType {Ship = 0, Missile = 1, Helicopter = 2, Land = 3};

public class Class {

	private string name;
	private int sprite;

	private ClassType type;
	private Country country;
	private List<Module> modules;
	private List<Class> missilesAutoDef;
	private List<Loadout> loadouts;


	public Class(JObject json, ClassType type) {
		this.type = type;

		name = (string)json["name"];
		sprite = (int)json["sprite"];

		country = GameController.getCountries()[(int)json["country"] - 1];

		modules = new List<Module>();

		foreach (string uniqueModuleName in json["modules"]) {
			modules.Add(GameController.moduleFromUniqueName(uniqueModuleName));
		}

		missilesAutoDef = new List<Class>();
		JToken token;
		if (json.TryGetValue("missileAutoDef", out token)) {
			foreach (string uniqueMissileName in json["missileAutoDef"]) {
				missilesAutoDef.Add(GameController.classFromUniqueName(uniqueMissileName));
			}
		}

		loadouts = new List<Loadout>();
		if (json.TryGetValue("loadouts", out token)) {
			foreach (JObject jsonLoadout in json["loadouts"]) {
				Loadout loadout = new Loadout((string)jsonLoadout["name"]);

				foreach (JObject ammoInfo in jsonLoadout["ammo"]) {
					loadout.addAmmo(GameController.classFromUniqueName((string)ammoInfo["class"]), (int)ammoInfo["count"]);
				}

				loadouts.Add(loadout);
			}
		}
	}

	public string getName() {
		return name;
	}

	public Sprite getSprite(Visibility visibility, Relation relation, bool isStacked, bool differentRelations) {
		return GameController.getSprite(sprite, visibility, relation, isStacked, differentRelations);
	}

	public Sprite getSelection(Visibility visibility, Relation relation) {
		return GameController.getSelection(sprite, visibility, relation);
	}

	public Country getCountry() {
		return country;
	}

	public List<Module> getModules() {
		return modules;
	}

	public List<ModuleUI> getModulesUI() {
		return null;
	}

	public ClassType getClassType() {
		return type;
	}

	public PathConstraints getPathConstraints() {
		switch (type) {
			default:
				return new PathConstraints(Constraint.Sea);
				
			case ClassType.Missile:
				return new PathConstraints(Constraint.Air);

			case ClassType.Helicopter:
				return new PathConstraints(Constraint.Air);

			case ClassType.Land:
				return new PathConstraints(Constraint.Land);
		}
	}

	public bool canHit(ClassType type) {
		foreach(Module module in modules) {
			if (module is GuidanceModule) {
				return ((GuidanceModule)module).canHit(type);
				//maybe change if multiple guidance
			}
		}

		return false;
	}

	public List<Class> getMissileAutoDef() {
		return missilesAutoDef;
	}

	public float getLaunchDistance() {
		foreach(Module module in modules) {
			if (module is CommandModule) {
				return ((CommandModule)module).getLaunchDistance();
				//maybe change if multiple guidance
			}
		}

		return 1000;
	}

	public Loadout getLoadout(string name) {
		foreach(Loadout loadout in loadouts) {
			if (loadout.getName().ToLower() == name.ToLower()) {
				return loadout;
			}
		}

		return null;
	}

	public static JObject jsonFromFile(string jsonPath) {
		StreamReader reader = File.OpenText(jsonPath);
		return (JObject)JToken.ReadFrom(new JsonTextReader(reader));
	}

	public static Class[] loadClasses(string[] filenames, ClassType type) {
		Class[] array = new Class[filenames.Length];

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

		return array;
	}
}
