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

public abstract class ContainerModule : Module {
	private float loadWaitingTime;
	private bool loadAmmo;

	public ContainerModule(JObject json) : base(json) {
		JToken token;
		if (json.TryGetValue("loadingTime", out token)) {
			loadWaitingTime = (float)json["loadingTime"];
		}
		else {
			loadWaitingTime = 1.0f;
		}

		if (json.TryGetValue("canLoadAmmo", out token)) {
			loadAmmo = (bool)json["canLoadAmmo"];
		}
		else {
			loadAmmo = false;
		}
	}

	public bool canLoadAmmo() {
		return loadAmmo;
	}

	public float getLoadWaitingTime() {
		return loadWaitingTime;
	}

	abstract public bool canStore(Class unitClass);
}

public abstract class ContainerModuleData : ModuleData {
	protected float loadWaitingTime;
	protected List<StoredUnit> storedUnits;

	public ContainerModuleData(int parent, Module template, Vector position) : base(parent, template, position) {
		storedUnits = new List<StoredUnit>();
	}

	//should only be called from StoredUnit's changeStore
	public void addToStored(StoredUnit stored) {
		storedUnits.Add(stored);
	}

	public void removeFromStored(StoredUnit unit) {
		storedUnits.Remove(unit);
	}

	//returns a unit of the right class which is not being loaded
	public StoredUnit getIdleStored(Class unitClass) {
		foreach(StoredUnit unit in storedUnits) {
			if (unit.getClass() == unitClass && !unit.isBeingLoaded()) {
				return unit;
			}
		}

		return null;
	}

	public List<StoredUnit> getAllStored() {
		return storedUnits;
	}

	abstract public List<StoredUnit> getUnitsOnDeck();

	public bool tryToTransfert(StoredUnit toBeMoved) {
		if (loadWaitingTime > 0.0f) {
			return false;
		}

		if (toBeMoved.getStore() != null && toBeMoved.getStore().loadWaitingTime > 0.0f) {
			return false;
		}

		if (toBeMoved.getStore() != this) {
			loadWaitingTime += ((ContainerModule)template).getLoadWaitingTime();

			if (toBeMoved.getStore() != null) {
				toBeMoved.getStore().loadWaitingTime += Mathf.Max(((ContainerModule)toBeMoved.getStore().template).getLoadWaitingTime(), ((ContainerModule)template).getLoadWaitingTime());
			}

			Requests.setStore(toBeMoved, this);
		}

		return true;
	}

	public int getNumberIdleStored(Class unitClass) {
		int total = 0;

		foreach(StoredUnit stored in storedUnits) {
			if(stored.getClass() == unitClass && stored.getLoadingState() == LoadingState.None && stored.getCurrentLoadout() == null) {
				total++;
			}
		}

		return total;
	}

	override public void updateTime(float delta) {
		loadWaitingTime = Mathf.Max(0.0f, loadWaitingTime - delta);
	}
}