using UnityEngine;

// Bewegt den Kopf der Schlange.
public class SnakeHeadMover : MonoBehaviour {

    /*
     * Bei "Drehungen" müssen wir ein Schlangenteil in die
     * entstehende Ecke einfügen - daher brauchen wir
     * Zugriff auf unseren "SnakeTailController".
     */
    public SnakeTailController tailController = null;

    // Die Geschwindigkeit der Schlange.
    public float velocity = 1F;

    // Wir prüfen regelmäßig, ob ein Apfel "in Sicht" ist
    public Transform forwardAppleCheck = null;

    // Die Zunge müssen wir abschalten, wenn die Schlange stirbt.
    public GameObject snakeTongue = null;

    // Die Kamera brauchen wir für die Kamera-Animation vor Äpfeln
    public Animator animatorCamera = null;

    // Lokale Animatoren - die können wir uns mit GetComponent holen
    private Animator animator = null;
    private Animator animatorTongue = null;

    // siehe Dokumentation in SnakeTailController
    public void Awake() {
        if (tailController == null) {
            Debug.LogError("Snake Tail Controller wurde nicht zugewiesen!");
            this.enabled = false; // diese Komponente abschalten
        }
        if (forwardAppleCheck == null) {
            Debug.LogError("Forward Apple Check wurde nicht zugewiesen!");
            this.enabled = false; // diese Komponente abschalten
        }
        if (snakeTongue == null) {
            Debug.LogError("Snake Tongue wurde nicht zugewiesen!");
            this.enabled = false; // diese Komponente abschalten
        }

        // Zum Steuern der Animationen
        animator = GetComponent<Animator>();
        animatorTongue = snakeTongue.GetComponent<Animator>();
    }

    public void Start() {
        /*
           * Idee: Zufällige Richtung (hoch, links, rechts oder runter).
           * dazu Random.Range(float min, float max) verwenden und
           * if-Abfrage mit verschiedenen Bereichsabfragen.
           * Siehe auch "CheckKeys" (die zufällige Richtung funktioniert
           * genau so - nur mit anderen Bedingungen innerhalb der if-Abfrage).
           */
    }

    /// <summary>
    ///     Update() wird einmal pro "Frame" automatisch von Unity
    ///     aufgerufen. Also jedes Mal, bevor Unity das aktuelle Bild
    ///     berechnet. Hier können z.B. Positionsveränderungen stehen.
    /// </summary>
    public void Update() {
        // zunächst prüfen wir, ob der Benutzer eine Taste gedrückt
        // hat und damit die Richtung wechselt

        CheckKeys();

        // Die Schlange bewegen
        transform.Translate(velocity * Vector3.up * Time.deltaTime);

        CheckGreed();
    }

    /// <summary>
    ///     Prüft, ob eine der Cursor-Tasten gedrückt wurde und
    ///     ändern dann die Richtung.
    /// </summary>
    public void CheckKeys() {
        int oldAngle = (int)transform.rotation.eulerAngles.z;
        int newAngle = oldAngle;
        /*
         * Wir verwenden "GetKeyDown", weil wir direkt beim nach unten
         * drücken der Taste reagieren wollen. GetKeyUp würde beim
         * Loslassen der Taste reagieren, GetKey liefert beim Halten
         * der Taste "true" als Ergebnis des Methodenaufrufes.
         */
        if (Input.GetKeyDown(KeyCode.UpArrow)) {
            newAngle = 0;
        } else if (Input.GetKeyDown(KeyCode.DownArrow)) {
            newAngle = 180;
        } else if (Input.GetKeyDown(KeyCode.RightArrow)) {
            newAngle = 270;
        } else if (Input.GetKeyDown(KeyCode.LeftArrow)) {
            newAngle = 90;
        }

        if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) {
            Vector2 touchPosition = Input.GetTouch(0).position;
            Debug.Log(string.Format("Touched: {0}", touchPosition));

            if (touchPosition.y > Screen.height - 150) {
                newAngle = 0;
            } else if (touchPosition.y < 150) {
                newAngle = 180;
            } else if (touchPosition.x > Screen.width - 150) {
                newAngle = 270;
            } else if (touchPosition.x < 150) {
                newAngle = 90;
            }
        }

        /*
         * falls die Richtung gewechselt wurde, brauchen wir an genau
         * dieser Stelle einen Schlangen-Teil.
         */
        if (oldAngle != newAngle) {
            transform.rotation = Quaternion.Euler(0, 0, newAngle);
            tailController.CreateNewTailPart(newAngle);
        }

        /*
         * Idee: Der Spieler kann "in die entgegengesetzte Richtung" wechseln,
         * was zu sofortigem Game-Over führt. Durch Prüfung, in welche Richtung
         * sich die Schlange gerade bewegt lässt sich dieses Problem beheben.
         * D.h. wenn der Benutzer "nach oben" drückt, und die Richtung gerade
         * "nach unten" ist, dann darf nichts passieren (und ebenso für
         * alle anderen Richtungen).
         */
    }

    private void CheckGreed() {
        Vector3 myPos = transform.position;
        Vector3 destPos = forwardAppleCheck.position;
        int applesLayer = LayerMask.GetMask("Apples");
        RaycastHit2D hit = Physics2D.Linecast(myPos, destPos, applesLayer);
        // wenn wir einen Apfel finden => gierig werden ;-)
        bool appleAhead = hit.collider != null;
        animator.SetBool("AppleAhead", appleAhead);
        animatorTongue.SetBool("AppleAhead", appleAhead);
        if (animatorCamera != null) {
            animatorCamera.SetBool("AppleAhead", appleAhead);
        }
    }

    public void DisableOnDeath() {
        // Zieh die Zunge ein ;-)
        snakeTongue.SetActive(false);

        // Schalte auf die Todes-Animation um (in diesem Fall nur ein Frame)
        animator.SetTrigger("SnakeDied");

        // schalt mich aus
        enabled = false;
    }

    public void DisableOnWin() {
        // Zieh die Zunge ein ;-)
        snakeTongue.SetActive(false);

        // Schalte auf die Todes-Animation um (in diesem Fall nur ein Frame)
        animator.SetTrigger("SnakeDone");

        // schalt mich aus
        enabled = false;
    }

}
