using UnityEngine;
using System.Collections;

public class SnakeCollisions : MonoBehaviour {

    /*
     * Das Vater-Transform der Äpfel - wenn das keine Kinder mehr hat,
     * ist der Level beendet.
     */
    public Transform apples = null;

    public float delaySecondsGameOver = 3F;

    public float delaySecondsLevelUp = 2F;

    public string nextLevel = "Level-01";

    public AudioSource eatApple = null;

    public AudioSource playerWon = null;

    public AudioSource gameOver = null;

    private GameGUI gameGUI = null;

    // siehe Dokumentation in SnakeTailController
    public void Awake() {
        if (apples == null) {
            Debug.LogError("Apples wurde nicht zugewiesen!");
            this.enabled = false; // diese Komponente abschalten
        }

        /*
         * Die Audio-Quellen (eatApple, playerWon, gameOver) werden nicht geprüft.
         * Falls diese nicht angegeben sind, werden die Sounds einfach ignoriert.
         */

        gameGUI = (GameGUI)Object.FindObjectOfType(typeof(GameGUI));
        if (gameGUI == null) {
            Debug.LogWarning("Diese Szene enthält keine GameGUI - daher werden keine Spielzustaende dargestellt");
        }
    }

    public void OnCollisionEnter2D(Collision2D collision) {
        Debug.Log("Collision detected");
    }

    /*
     * Wird von Unity aufgerufen, wenn die Schlange irgendeinen Collider
     * berührt. OnTriggerEnter ist allerdings für unsere Zwecke geeigneter
     * als OnCollisionEnter, da wir nur auf das Ereignis reagieren wollen
     * und uns z.B. Details wie wer hat wen wo berührt und wie "stark" nicht
     * interessieren.
     */
    public void OnTriggerEnter2D(Collider2D other) {
        /*
         * je nachdem, welches "Tag" der andere hat (mit Tags können Objekte
         * "markiert" werden)
         */
        switch (other.tag) {
            case "Level":
                RanIntoWall();
                break;
            case "Player":
                RanIntoSelf();
                break;
            case "Apple":
                AteApple(other.gameObject);
                break;
        }
    }

    private void RanIntoWall() {
        Debug.Log("Der Spieler ist in eine Wand gelaufen - GAME OVER");

        PlaySound(gameOver);

        StartCoroutine(HandleGameOver());
    }

    private void RanIntoSelf() {
        Debug.Log("Der Spieler ist in sich selbst gelaufen - GAME OVER");

        PlaySound(gameOver);

        StartCoroutine(HandleGameOver());
    }

    private IEnumerator HandleGameOver() {
        DeactivateSnakeDeath();

        // wenn wir eine GameGUI gefunden haben ...
        if (gameGUI != null) {
            gameGUI.currentGameMode = GameMode.GameOver;
        }

        yield return new WaitForSeconds(delaySecondsGameOver);

        Application.LoadLevel("MainMenu");
    }

    private void AteApple(GameObject apple) {
        Debug.Log(string.Format("Der Spieler hat einen Apfel gegessen und wird jetzt laenger, noch {0} Aepfel!",
            apples.childCount - 1));

        PlaySound(eatApple);

        /*
         * wenn SnakeCollisions und SnakeTailController an das gleiche GameObject
         * gehängt wurden (SnakeHead), kann man in SnakeCollisions über
         * GetComponent<SnakeTailController>() Zugriff auf SnakeTailController
         * erhalten, ohne im Editor eine entsprechende Referenz herstellen zu müssen.
         */
        SnakeTailController tailController = GetComponent<SnakeTailController>();
        tailController.EatOneApple();

        // wenn der Apfel gegessen wurde, verschwindet er
        Destroy(apple);

        if (apples.childCount == 1) { // offenbar zählt das Objekt selbst auch schon als "Kind"
            Debug.Log("GEWONNEN - auf in den naechsten Level!!!");
            StartCoroutine(HandleGameLevelUp());
        }
    }

    private IEnumerator HandleGameLevelUp() {
        DeactivateSnakeWon();

        PlaySound(playerWon);

        // wenn wir eine GameGUI gefunden haben ...
        if (gameGUI != null) {
            gameGUI.currentGameMode = GameMode.LevelUp;
        }

        yield return new WaitForSeconds(delaySecondsLevelUp);

        Application.LoadLevel(nextLevel);
    }

    private void DeactivateSnakeDeath() {
        SnakeHeadMover mover = GetComponent<SnakeHeadMover>();
        mover.DisableOnDeath();

        SnakeTailController controller = GetComponent<SnakeTailController>();
        controller.DisableOnDeath();

        // Die Kamera soll auch stehen bleiben
        FindObjectOfType<Simple2DFollow>().enabled = false;
    }

    private void DeactivateSnakeWon() {
        SnakeHeadMover mover = GetComponent<SnakeHeadMover>();
        mover.DisableOnWin();

        SnakeTailController controller = GetComponent<SnakeTailController>();
        controller.DisableOnWin();

        // Die Kamera soll auch stehen bleiben
        FindObjectOfType<Simple2DFollow>().enabled = false;
    }

    private void PlaySound(AudioSource audioSource) {
        /*
         * Da wir die Zuweisung der Audio-Quellen nicht in Awake() prüfen,
         * prüfen wir sie hier beim Abspielen. Falls die Audio-Quelle
         * audioSource nicht zugewiesen ist, ertönt einfach kein Klang.
         */
        if (audioSource != null) {
            audioSource.Play();
        }
    }

}
