using UnityEngine;
using UnityEngine.UI;

public class Typewriter : MonoBehaviour {

    [SerializeField] private int lettersPerSecond = 30;
    [SerializeField] private GameObject paper = null;

    private static Text text = null;

    private static string[] msg = new string[] { "Bien arrivé sur l'île.\n\nRécapitulatif de mission :\nTenter de comprendre ce qu'il se passe ici.\n\nJ'ai déjà trouvé plusieurs informations,\nayant plus ou moins de sens.\n\nJ'ai également trouvé un phare, sans échelle.\nTrès étrange. Je dois trouver un moyen de monter.\n\nIl y a également une très vieille épave.\nJe me demande bien comment elle a pu arriver là.\n\nLa dernière note que j'ai lue est alarmante.\nIl ne fait pas bon être dehors la nuit, ici.\nJe devrais garder ça à l'esprit.",
                                                 "Pour une raison inconnue,\nune échelle est apparue dans le phare.\n\nCependant, il manquait des barreaux.\nJ'ai passé ma journée à les chercher !\n\nUne fois arrivé en haut, j'ai constaté qu'il\nn'y avait pas d'électricité, et comme par hasard,\nla nuit est tombée alors que je redescendais.\n\nCette île me paraît de plus en plus étrange...",
                                                 "Ce moulin n'était pas là hier... Très bizarre.\nJ'y ai trouvé de quoi remettre l'électricité\ndans le phare.\n\nAvec quelques réglages,\nj'ai pu diriger la lumière du phare\nvers la grotte, derrière la cascade.\n\nJ'ai enfin pu lire ce qui y était dessiné !\nUn dessin d'enfant dans lequel\nétait caché un code, un nombre en latin\nqui m'a permis d'ouvrir la porte blindée sous l'eau,\nà l'aide d'une interface digitale apparue\nen même temps que le moulin...\n\nJ'ai ainsi trouvé une grotte souterraine, où il\nn'y avait rien d'autre qu'un bâton de dynamite.\n\nLorsque je suis remonté à la surface,\nla nuit était tombée.\nJe verrai ce que je peux faire de ça demain.",
                                                 "Je em snes mal...\n\nJ'ai ulitisé la dnyatime sur al monagtne\npuor mnoter au smomet,\n\nMias l'epxolsoin étiat puls frote que pévru...\nJ'ai toruvé une cbaane, je pnese que je puex\nm'en sverir puor m'nevoler, et qiutter\nctete île de mhaluer...\n\nJe n'aruias psa dû mnaegr ces chmapingonns...",
                                                 "J'en ai littéralement vu\nde toutes les couleurs aujourd'hui.\nJe vais beaucoup mieux maintenant.\nJ'ai récupéré un réacteur sur l'étagère.\nJe compte bien m'en servir sur la cabane,\npour m'envoler de cet endroit maudit.\nIl ne me reste qu'à trouver un moyen de planer\nune fois dans les airs..."
                                                };

    private static int idx;

    private static Typewriter instance = null;

    private static bool isWriting = false;

    private static Image paperImage = null;

    private static bool waitingForValidation = false;

    private static float alpha = 1f;

    private const float pagingOutSpeed = 50f;
    private static int pagingIn = 1;
    private static bool isPagingIn = false;
    private static bool isPagingOut = false;

    private static float originalPaperY = 0f;
    private static float originalTypewriterY = 0f;

	void Start() {
        if (instance != null) {
            Debug.LogError("Error : only one instance of Typewriter must be running at a time !");
            return;
        }
        instance = this;
        text = GetComponent<Text>();
        if (text == null) {
            Debug.LogError("Error : There must be a Text component on this GameObject !");
            return;
        }
        text.text = "";
        paperImage = paper.GetComponent<Image>();
        // On place la feuille pile en-dessous l'écran
        ResetPaperPosition();
        originalTypewriterY = transform.localPosition.y;
        originalPaperY = -paperImage.rectTransform.localPosition.y;
        if (FadeManager.currentDay < msg.Length) {
            Write();
        } else {
            Debug.LogError("Error : No more paper to write !");
        }
        if (FadeManager.currentDay == 4 && RotateSkybox.skyboxMat != null) {
            RotateSkybox.skyboxMat.SetColor("_Tint", new Color(0.5f, 0.5f, 0.5f));
        }
    }

    void Update() {
        if (isPagingIn) {
            iTween.MoveBy(paper, iTween.Hash("amount", originalPaperY / 3f * Vector3.up, "time", 0.5f, "easetype", iTween.EaseType.easeOutExpo, "oncomplete", "PagingInPlus", "oncompletetarget", gameObject));
        }
        if (waitingForValidation && (Input.GetButtonDown("Submit") || Input.GetKeyDown(KeyCode.KeypadEnter) || Input.GetButtonDown("Action") || Input.GetButtonDown("Jump") || Input.GetMouseButtonDown(0))) {
            waitingForValidation = false;
            CancelInvoke("Blinking");
            FadeManager.DoFadeOut("MainScene_"+(FadeManager.currentDay+1));
            InvokeRepeating("FadeOut", 0, 1 / FadeManager.fpsStatic);
            SoundManager.PlaySound("ding");
            Invoke("PageOut", 0.5f);
        }
        if (isWriting && (Input.GetMouseButtonDown(0) || Input.GetButton("Action") || Input.GetButtonDown("Submit") || Input.GetButtonDown("Jump"))) {
            EndWriting();
        }
        if (isPagingOut) {
            paper.transform.Translate(Vector3.down * pagingOutSpeed * Time.deltaTime);
            transform.Translate(Vector3.down * pagingOutSpeed * Time.deltaTime);
        }
    }

    public static void Write() {
        if (!isWriting) {
            idx = 0;
            SoundManager.PlaySound("page_in");
            instance.Invoke("MovePaperUp", 0.3f);
            instance.Invoke("MovePaperUp", 0.8f);
            instance.Invoke("MovePaperUp", 1.3f);
            instance.Invoke("Writing", 1.3f);
            msg[FadeManager.currentDay] = (FadeManager.currentDay != 3 ? "Jour " : "Juor ") + (FadeManager.currentDay+1).ToString() + "\n\n" + msg[FadeManager.currentDay] + "\n\n\n" + (FadeManager.currentDay != 3 ? "Inspecteur Tails" : "Isnpetcuer Tials");
            instance.Invoke("WriteMessage", 2);
        }
    }

    void ResetPaperPosition() {
        paperImage.rectTransform.localPosition = (paperImage.rectTransform.rect.height + (Screen.height - paperImage.rectTransform.rect.height) / 2) * Vector3.down;
    }

    void Writing() {
        isWriting = true;
    }

    void MovePaperUp() {
        isPagingIn = true;
    }

    void PagingInPlus() {
        pagingIn++;
        if (pagingIn == 3) {
            isPagingIn = false;
        }
    }

    void PageOut() {
        SoundManager.PlaySound("page_out");
        isPagingOut = true;
    }

    void ResetPaper() {
        ResetPaperPosition();
        isPagingOut = false;
        pagingIn = 1;
        transform.localPosition = new Vector3(transform.localPosition.x, originalTypewriterY, 0);
        text.color = new Color(0, 0, 0, 1);
        paperImage.color = new Color(1, 1, 1, 1);
        text.text = "";
        alpha = 1;
    }

    void FadeOut() {
        alpha -= 1 / (FadeManager.fpsStatic * FadeManager.fadeDurationStatic / 2);
        text.color = new Color(0, 0, 0, alpha);
        paperImage.color = new Color(1, 1, 1, alpha);
        if (alpha < 0) {
            alpha = 0;
            CancelInvoke("FadeOut");
            ResetPaper();
            FadeManager.DoFadeIn();
        }
    }

    void Blinking() {
        if (text.text.Contains(">")) {
            text.text = msg[FadeManager.currentDay];
        } else {
            text.text = msg[FadeManager.currentDay] + " > ";
        }
    }

    void WriteMessage() {
        idx++;
        if (idx < msg[FadeManager.currentDay].Length) {
            text.text = msg[FadeManager.currentDay].Substring(0, idx);
            if (msg[FadeManager.currentDay][idx] == '\n' && msg[FadeManager.currentDay][idx-1] != '\n') {
                SoundManager.StopSound("writing");
                SoundManager.PlaySound("line_break");
                instance.Invoke("WriteMessage", 0.6f + 1f / lettersPerSecond); // 0.6 correspond à la longueur du son line_break
            } else if (msg[FadeManager.currentDay][idx] != ' ' || msg[FadeManager.currentDay][idx] == ' ' && msg[FadeManager.currentDay][idx-1] != ' ') {
                instance.Invoke("WriteMessage", 1f / lettersPerSecond);
                if (!SoundManager.SoundIsPlaying("writing")) {
                    SoundManager.PlaySound("writing");
                }
            } else {
                // On zappe les temps d'attente s'il y a plusieurs espaces à la suite
                WriteMessage();
            }
        } else {
            EndWriting();
        }
    }

    void EndWriting() {
        CancelInvoke("WriteMessage");
        text.text = msg[FadeManager.currentDay];
        isWriting = false;
        SoundManager.StopSound("writing");
        waitingForValidation = true;
        instance.InvokeRepeating("Blinking", 0, 0.5f);
    }
}