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

public class Gnome : MonoBehaviour {

	// Obiekt, który ma śledzić kamera
	public Transform cameraFollowTarget;

	public Rigidbody2D ropeBody;

	public Sprite armHoldingEmpty;
	public Sprite armHoldingTreasure;

	public SpriteRenderer holdingArm;

	public GameObject deathPrefab;
	public GameObject flameDeathPrefab;
	public GameObject ghostPrefab;

	public float delayBeforeRemoving = 3.0f;
	public float delayBeforeReleasingGhost = 0.25f;

	public GameObject bloodFountainPrefab;

	bool dead = false;

	bool _holdingTreasure = false;

	public bool holdingTreasure {
		get {
			return _holdingTreasure;
		}
		set {
			if (dead == true) {
				return;
			}

			_holdingTreasure = value;

			if (holdingArm != null) {
				if (_holdingTreasure) {
					holdingArm.sprite = armHoldingTreasure;
				} else {
					holdingArm.sprite = armHoldingEmpty;
				}
			}

		}
	}

	public enum DamageType {
		Slicing,
		Burning
	}

	public void ShowDamageEffect(DamageType type) {
		switch (type) {

		case DamageType.Burning:
			if (flameDeathPrefab != null) {
				Instantiate(
					flameDeathPrefab,cameraFollowTarget.position, 
					cameraFollowTarget.rotation);
			}
			break;

		case DamageType.Slicing:
			if (deathPrefab != null) {
				Instantiate(
					deathPrefab, 
					cameraFollowTarget.position, 
					cameraFollowTarget.rotation
				);
			}
			break;
		}
	}

	public void DestroyGnome(DamageType type) {

		holdingTreasure = false;

		dead = true;

		// Odnajdujemy obiekty podrzędne i losowo rozłączamy ich złączenia
		foreach (BodyPart part in GetComponentsInChildren<BodyPart>()) {

			switch (type) {

			case DamageType.Burning:
				// Obrażenia są zadawane w 1/3 przypadków
				bool shouldBurn = Random.Range (0, 2) == 0;
				if (shouldBurn) {
					part.ApplyDamageSprite(type);
				}
				break;

			case DamageType.Slicing:
				// Obrażenia typu Slicing zawsze powodują zastosowanie 
				// odpowiedniego sprajtu
				part.ApplyDamageSprite (type);

				break;
			}

			// W 1/3 przypadków obrażenie kończy się oderwaniem kończyny
			bool shouldDetach = Random.Range (0, 2) == 0;

			if (shouldDetach) {

				// Po zatrzymaniu obiektu usuwamy z niego komponent 
				// RigidBody i komponent wykrywania kolizji
				part.Detach();

				// Jeśli oddzielamy kończynę krasnala i jeśli obrażenie było 
				// typu Slicing, to dodajemy fontannę krwi

				if (type == DamageType.Slicing) {

					if (part.bloodFountainOrigin != null && 
						bloodFountainPrefab != null) {

						// Dołączamy fontannę krwi dla tej odłączonej części krasnala
						GameObject fountain =  Instantiate(
							bloodFountainPrefab, 
							part.bloodFountainOrigin.position, 
							part.bloodFountainOrigin.rotation
						) as GameObject;

						fountain.transform.SetParent(
							this.cameraFollowTarget, 
							false
						);
					}
				}

				// Odłączamy ten obiekt
				var allJoints = part.GetComponentsInChildren<Joint2D>();
				foreach (Joint2D joint in allJoints) {
					Destroy (joint);
				}
			}
		}

		// Dodajemy do tego obiektu komponent RemoveAfterDelay
		var remove = gameObject.AddComponent<RemoveAfterDelay>();
		remove.delay = delayBeforeRemoving;


		StartCoroutine(ReleaseGhost());
	}

	IEnumerator ReleaseGhost() {

		// Nie ma prefabrykatu ducha? To go pomijamy...
		if (ghostPrefab == null) {
			yield break;
		} 

		// Czekamy liczbę sekund określoną przez właściwość 
		// delayBeforeReleasingGhost
		yield return new WaitForSeconds(delayBeforeReleasingGhost);

		// Dodajemy ducha
		Instantiate(
			ghostPrefab, 
			transform.position, 
			Quaternion.identity
		);
	}
}
