using Assets;
using Assets.Scripts;
using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;

public class DatingController : MonoBehaviour
{
    public static string Preference = "Both";
    public static int Hearts = 0;

    public Dictionary<string, Sprite> FaceSprites;
    public Dictionary<string, Sprite> GiftSprites;

    [SerializeField] PersonController Person1;
    [SerializeField] PersonController Person2;
    [SerializeField] TMP_Text HeartsText;
    [SerializeField] TMP_Text TimerText;
    [SerializeField] TMP_Text QuestionText;
    [SerializeField] TMP_Text AnswerText;
    [SerializeField] TMP_Text IncrementText;

    [SerializeField] TMP_Text CountdownText;
    [SerializeField] TMP_Text CountdownTextShadow;

    [SerializeField] List<CloudController> Clouds;
    [SerializeField] List<GiftController> GiftButtons;
    [SerializeField] ClockHandController Clock;

    [SerializeField] ParticleSystem SmallHearts;
    [SerializeField] ParticleSystem BigHearts;

    List<Gift> CurrentGifts;

    bool Person1Active = false;
    bool StartGame = false;
    bool CloudsActive = false;
    float Timer;
    bool DateActive;
    int QuestionTextIndex;
    int AnswerTextIndex;

    bool Question1Asked = false;
    bool Question2Asked = false;
    bool Question3Asked = false;

    Tween QuestionTween;
    Tween AnswerTween;

    AudioPlayerController AudioPlayer;

    private void Awake()
    {
        FaceSprites = new Dictionary<string, Sprite>();
        GiftSprites = new Dictionary<string, Sprite>();

        var faceSprites = Resources.LoadAll<Sprite>("Faces");
        foreach (var face in faceSprites)
        {
            FaceSprites[face.name] = face;
        }

        var giftSprites = Resources.LoadAll<Sprite>("Gifts");
        foreach (var gift in giftSprites)
        {
            GiftSprites[gift.name] = gift;
        }
    }

    public static DatingController GetController()
    {
        return GameObject.FindObjectOfType<DatingController>();
    }

    void Start()
    {
        AudioPlayer = FindObjectOfType<AudioPlayerController>();
        Questions.InitQuestions();
        Gifts.InitGifts();
        StartGame = false;
        Hearts = 0;
        Timer = 90;
        QuestionText.text = "";
        AnswerText.text = "";
        IncrementText.text = "";

        CountdownText.DOFade(0, 1f).SetEase(Ease.Linear)
            .OnComplete(() =>
            {
                CountdownText.color = Color.white;
                CountdownText.text = "SET...";

                CountdownText.DOFade(.25f, 1f).SetEase(Ease.Linear)
                    .OnComplete(() =>
                    {
                        CountdownText.color = Color.white;
                        CountdownText.text = "DATE!";
                        

                        CountdownText.DOFade(.25f, 1f).SetEase(Ease.Linear)
                        .OnComplete(() => {
                            NextPerson(0);
                            StartGame = true;
                            CountdownText.gameObject.SetActive(false);
                            CountdownTextShadow.gameObject.SetActive(false);
                        });
                    });
            })
            .SetDelay(1f);

        CountdownTextShadow.DOFade(0, 1f).SetEase(Ease.Linear)
            .OnComplete(() =>
            {
                CountdownTextShadow.color = new Color(CountdownTextShadow.color.r, CountdownTextShadow.color.g, CountdownTextShadow.color.b);
                CountdownTextShadow.text = "SET...";

                CountdownTextShadow.DOFade(0, 1f).SetEase(Ease.Linear)
                    .OnComplete(() =>
                    {
                        CountdownTextShadow.color = new Color(CountdownTextShadow.color.r, CountdownTextShadow.color.g, CountdownTextShadow.color.b);
                        CountdownTextShadow.text = "DATE!";

                        CountdownTextShadow.DOFade(0, 1f).SetEase(Ease.Linear);
                    });
            })
            .SetDelay(1f);
    }

    void Update()
    {
        if (StartGame)
        {
            Timer -= Time.deltaTime;

            if (Timer < 0)
            {
                StopGame();
            }
            else
            {
                var span = TimeSpan.FromSeconds(Timer);
                TimerText.text = span.ToString(@"mm\:ss\.ff");
            }
        }

        HeartsText.text = Hearts.ToString();
    }

    void StopGame()
    {
        DOTween.KillAll();
        SceneManager.LoadScene(2);
    }

    void RestartGame(string preference)
    {
        Preference = preference;
        SceneManager.LoadScene(1);
    }

    PersonController GetPerson()
    {
        return Person1Active ? Person1 : Person2;
    }

    void SetCloudStatus(bool active)
    {
        Clouds.ForEach(cloud => cloud.gameObject.SetActive(active));
    }

    public void AskQuestion(int index)
    {
        if (CloudsActive)
        {
            if (index == 0)
                Question1Asked = true;
            if (index == 1)
                Question2Asked = true;
            if (index == 2)
                Question3Asked = true;

            CloudsActive = false;
            var person = GetPerson();

            AnswerText.text = "";
            QuestionText.text = "";
            GiftButtons.ForEach(g => g.Enable());

            QuestionTween = SetQuestionText(person.Questions[index].Text)
                .OnComplete(() =>
                {
                    PlayVoiceLine(person, "Voice");
                    AnswerTween = SetAnswerText(person.Answers[index].Text).OnComplete(() => CloudsActive = true);
                });
        }
    }

    void PlayVoiceLine(PersonController person, string line, int max = 4)
    {
        var voiceIndex = UnityEngine.Random.Range(1, max);
        var key = $"{person.Gender}_{line}_{voiceIndex}";
        Debug.Log(key);
        AudioPlayer.PlayClip(key);
    }

    public void GiveGift(int index)
    {
        if (Question1Asked || Question2Asked || Question3Asked)
        {
            AnswerTween.Kill();
            QuestionTween.Kill();

            DateActive = false;
            var person = GetPerson();
            var points = person.EvaluateGift(GiftButtons[index].Gift);
            GiftButtons.ForEach(g => g.Disable());
            SetCloudStatus(false);

            QuestionText.text = "";
            Tween thanksTween = null;

            if (points >= 2)
            {
                PlayVoiceLine(person, "Wow", 3);
                thanksTween = SetAnswerText("Wow, I love it!");
                BigHearts.Play();
            }
            else if (points == 1)
            {
                PlayVoiceLine(person, "Wow", 3);
                thanksTween = SetAnswerText("Thanks, I appreciate it.");
                SmallHearts.Play();
            }
            else if (points == 0)
            {
                PlayVoiceLine(person, "Bye", 3);
                thanksTween = SetAnswerText("Oh, um, thanks.");
            }
            else if (points < 0)
            {
                PlayVoiceLine(person, "Bye", 3);
                thanksTween = SetAnswerText("Uh...I think you should keep it.");
            }

            if (Question1Asked && points > 0) points++;
            if (Question2Asked && points > 0) points++;
            if (Question3Asked && points > 0) points++;

            Hearts += points;

            if (points != 0)
            {
                IncrementText.transform.localPosition = new Vector3(240, 0, 0);
                IncrementText.color = new Color(IncrementText.color.r, IncrementText.color.g, IncrementText.color.b);
                IncrementText.text = $"{(points > 0 ? "+" : "-")}{points}";
                IncrementText.transform.DOLocalMoveY(50, 3f);
                IncrementText.DOFade(0, 3f);
            }

            Clock.ResetClock();
            thanksTween.OnComplete(() => NextPerson()); 
            EventSystem.current.SetSelectedGameObject(null);
        }
    }

    void NextPerson(float delay = 1f)
    {
        QuestionTween.Kill();
        AnswerTween.Kill();
        DateActive = false;

        var oldPerson = GetPerson();
        Person1Active = !Person1Active;
        var newPerson = GetPerson();
        newPerson.Randomize();

        QuestionText.text = "";
        SetCloudStatus(false);
        GiftButtons.ForEach(g => g.Disable());

        oldPerson.transform.DOLocalMoveX(-2000, delay)
            .OnComplete(() =>
            {
                QuestionText.text = "";
                oldPerson.transform.localPosition = new Vector3(567, -224, 0);
                GetGiftsForPerson();
                newPerson.transform.DOLocalMoveX(-691, 1f)
                .OnComplete(() =>
                {
                    DateActive = true;
                    if (oldPerson != null)
                        Clock.StartClock().OnComplete(() => { PlayVoiceLine(newPerson, "Bye", 3); AnswerText.text = "Time's up! Bye!"; NextPerson(); });
                    foreach (var cloud in Clouds)
                    {
                        cloud.SetStartPosition();
                    }
                    SetCloudStatus(true);
                    PersonIntro();
                });
            });
    }

    void GetGiftsForPerson()
    {
        CurrentGifts = new List<Gift>();
        var person = GetPerson();
        var ordered = Gifts.GiftList.OrderBy(g => person.EvaluateGift(g)).ToList();
        CurrentGifts.Add(ordered.First());
        CurrentGifts.Add(ordered.Last());
        CurrentGifts.Add(ordered[UnityEngine.Random.Range(1, ordered.Count - 2)]);

        Debug.Log(CurrentGifts[0].Name + ": " + person.EvaluateGift(CurrentGifts[0]));
        Debug.Log(CurrentGifts[1].Name + ": " + person.EvaluateGift(CurrentGifts[1]));
        Debug.Log(CurrentGifts[2].Name + ": " + person.EvaluateGift(CurrentGifts[2]));

        var randomGifts = ArrayUtilities.GetRandomSubset(CurrentGifts, 3);
        GiftButtons[0].SetGift(randomGifts[0]);
        GiftButtons[1].SetGift(randomGifts[1]);
        GiftButtons[2].SetGift(randomGifts[2]);
    }

    void PersonIntro()
    {
        var person = GetPerson();

        Question1Asked = false;
        Question2Asked = false;
        Question3Asked = false;

        QuestionText.text = "";
        PlayVoiceLine(person, "Hello", 3);
        AnswerText.text = $"Hi, I'm {person.Name}!";
        SetCloudStatus(true);
        CloudsActive = true;
    }

    Tween SetQuestionText(string text)
    {
        QuestionTextIndex = 0;
        return DOTween.To(() => QuestionTextIndex, x =>
        {
            QuestionTextIndex = x;
            QuestionText.text = text.Substring(0, QuestionTextIndex);
        }, text.Length, .5f).SetEase(Ease.Linear);
    }

    Tween SetAnswerText(string text)
    {
        AnswerTextIndex = 0;
        return DOTween.To(() => AnswerTextIndex, x =>
        {
            AnswerTextIndex = x;
            AnswerText.text = text.Substring(0, AnswerTextIndex);
        }, text.Length, 1f).SetEase(Ease.Linear);
    }
}
