using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;

public class Game : MonoBehaviour {

	public const float kDayDuration = 40f;
	public const float kNightDuration = kDayDuration / 2f;
	public const float kRainTurnDuration = kDayDuration / 2f;
	public const float kWorkTick = 2f; // things are harvested every 2s
	public const float kMaxResource = 150f;


	public static void PlaySfx(string name) {
		instance.__sfx.play_sfx(name);
	}
	SFX __sfx;


	public Image foodBar;
	public Image waterBar;



	public float nextWorkTick;

	public List<Sprite> iconSprites; // hardcodeado MAAAAL

	public List<Human> allHumans;


	public Image night; // QUICK FIX BC FUCK SHADERSSSS!

	// 7 days w/o rain for a full drought, 7 days w/ for full flood
	public const int kFullDisasterWaterLevel = 7;
	// at -3 or +3 water level, player sees bad effects in soil
	public const float kWaterLevelForVisualEffect = 3;
	// can't ever go beyond +10 or -10
	public const int kDisasterWaterLevelMax = 10;
	// sunset/sunrise duration (fade in/out) for a 40s long day is 2s
	public const float kSunsetDuration = 20f / kDayDuration;

	public SpriteRenderer srDrought;
	public SpriteRenderer srFlood;
	SpriteRenderer srCurrentDisaster = null;

	public float dayStartedAt;
	public int dayNum = 0;
	public bool daylight = true;
	public float TimeOfDay { get { return (Time.time - dayStartedAt); } }

	public Player player1;
	public Player player2;

	public ParticleSystem psRain;
	GameObject goRain;
	float nextRainTurnTime;

	public Light sunlight;
	float targetSunlightIntensity;

	public RitualArea ritualArea;

	static public Game instance;

	public int waterLevel = 0; // too negative = drought; too positive = flood

	void Awake () {
		instance = this;
	}

	void Start () {
		__sfx = GetComponent<SFX>();
		ritualArea = FindObjectOfType<RitualArea>();
		goRain = psRain.gameObject;

		nextRainTurnTime = Time.time + kRainTurnDuration;
		nextWorkTick = Time.time + kWorkTick;

		allHumans = new List<Human>(player1.humans);
		allHumans.AddRange(player2.humans);

		NightEnd();
		UpdateHUD();
	}

	void OnDestroy () {
		instance = null;
	}

	bool rain = false;
	public bool Rain {
		get { return rain; }
		set { 
			if (rain == value)
				return;
			rain = value;
			if (rain) {
				// ParticleSystem.Play() DOES NOT WORK!!!
				goRain.SetActive(false);
				goRain.SetActive(true);

				ritualArea.BonfireOn = false;
			} else {
				psRain.Stop();

				if (!daylight)
					ritualArea.BonfireOn = true;
			}
		}
	}

	void UpdateHUD () {
		foodBar.fillAmount = Mathf.Clamp01(resources ["food"] / kMaxResource);
		waterBar.fillAmount = Mathf.Clamp01(resources ["water"] / kMaxResource);
	}


	bool cacaDeMierda = false;

	void Update () {

		if (!cacaDeMierda) {
			cacaDeMierda = true;
			PlaySfx("music");
		}
			
			
		
		if (Input.GetKeyDown(KeyCode.Escape))
			Application.LoadLevel("Intro");

		if (Time.time > nextWorkTick) {
			nextWorkTick = Time.time + kWorkTick;
			foreach (Human h in allHumans)
				h.WorkTick();

			ritualArea.WorkTick();

			Harvest("water", -1.5f);
			Harvest("food", -1.5f);

			UpdateHUD();
		}

		if (Time.time > nextRainTurnTime) {
			nextRainTurnTime = Time.time + kRainTurnDuration;
			RainTurnEnd();
		}

		if (daylight && TimeOfDay > kDayDuration) {
			NightStart();
		} else if (!daylight && TimeOfDay > kDayDuration + kNightDuration) {
			NightEnd();
		}

		if (Cheater.cheatMode && Cheater.forceDay) {
			sunlight.intensity = 1;
		} else if (sunlight.intensity != targetSunlightIntensity) {
			sunlight.intensity += kSunsetDuration * Time.deltaTime * (targetSunlightIntensity > sunlight.intensity ? 1 : -1);
			sunlight.intensity = Mathf.Clamp01(sunlight.intensity);
		}

		UpdateQuickFixNight();
	}

	void UpdateQuickFixNight () {
		Color c = night.color;
		c.a = (1f - sunlight.intensity) * 0.66f;
		night.color = c;
	}

	void RainTurnEnd () {
		Rain = (Cheater.cheatMode && Cheater.forceDry) ? false : ((Cheater.cheatMode &&Cheater.forceRain) ? true : Random.value > 0.5f);
		waterLevel = Mathf.Clamp(waterLevel + (Rain ? 1 : -1), -kDisasterWaterLevelMax, kDisasterWaterLevelMax);

		int absLevel = Mathf.Abs(waterLevel);
		bool disaster = absLevel >= kWaterLevelForVisualEffect;
		// if disaster just started or just ended
		if ((srCurrentDisaster != null) != disaster) {
			if (disaster) // must get correct sr
				srCurrentDisaster = waterLevel > 0 ? srFlood : srDrought;
			srCurrentDisaster.enabled = disaster;
			if (!disaster) // discard old sr
				srCurrentDisaster = null;
		}

		// if there is a disaster currently
		if (disaster) {
			var c = srCurrentDisaster.color;
			var pepe = Mathf.InverseLerp(kWaterLevelForVisualEffect - 1, kFullDisasterWaterLevel, absLevel);
			c.a = pepe;
			srCurrentDisaster.color = c;
		}
		

	}

	void NightStart () {
		daylight = false;
		if (!Rain)
			ritualArea.BonfireOn = true;
		targetSunlightIntensity = 0;
	}

	void NightEnd () {
		daylight = true;
		dayNum++;
		dayStartedAt = Time.time;

		ritualArea.BonfireOn = false;

		targetSunlightIntensity = 1;


		if (dayNum > 1)
			PlaySfx("music");

	}

	public Dictionary<string, float> resources = new Dictionary<string, float> { { "food", 40 }, { "water", 40 } };
	public void Harvest (string resource, float amount) {
		resources[resource] += amount;
		resources[resource] = Mathf.Clamp(resources[resource], 0, kMaxResource);
	}

	public void OnBonfireChange () {
		foreach (Human h in allHumans)
			h.UpdateDance();
	}

	public void Kill (Human human) {
		if (player1.humans.Contains(human)) {
			if (human.Selected)
				player1.SelectNext();
			player1.humans.Remove(human);
		}
		if (player2.humans.Contains(human)) {
			if (human.Selected)
				player2.SelectNext();
			player2.humans.Remove(human);
		}
		allHumans.Remove(human);
		Destroy(human.gameObject);
	}
}
