using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class DishingMinigame : MonoBehaviour
{
    [System.Serializable]
    struct Plate
    {
        public SpriteRenderer dirty;
        public Sprite clean;
    }

    [SerializeField]
    GameObject
        doneImage,
        plateUI,
        disher;
    [SerializeField]
    int
        rotationsNeeded;
    [SerializeField]
    int
        platesToDish,
        scorePerPlate;
    [SerializeField]
    Animator
        disherAnim;
    Animator
        plateAnim;

    [SerializeField]
    GameObject
        miniGameParent,
        startPlate,
        gameSquare;

    [SerializeField]
    List<Plate>
        plates;
    
    ParticleSystem cleanDish;
        

    [SerializeField] ParticleSystem
        foam;
    
    [SerializeField] VerticalLayoutGroup 
        dishStack;

    float 
        oldX,
        oldY,
        rotatecount;
    int
        platesDone,
        nexPlate = 0,
        platesTotal = 0;
    public float MinRotSpd;
    Vector2 inputdirect;
    GameObject activePlate, oldPlate;

    float mediumSpeed;

    DishingSoundScript disherSound;

    Vector3 minigameScreenOrigPos = Vector3.up;

    float shakeTimer;

    enum State { dish, wait};
    State state = State.dish;

    public UnityEvent DishesDoneEvent = new UnityEvent();

    private bool initialized = false;

    private void Start()
    {
        activePlate = startPlate;
        plateAnim = activePlate.GetComponent<Animator>();
        disherSound = disher.GetComponent<DishingSoundScript>();
        minigameScreenOrigPos = gameSquare.transform.position;

    }

    private void Awake()
    {
        SpawnDish();
        minigameScreenOrigPos = gameSquare.transform.position;
    }

    void Update()
    {
        switch (state)
        {
            case State.dish:
                SpinToWin();
                break;
            case State.wait:
                break;
            default:
                break;
        }
    }
    private void SpinToWin()
    {
        float deltaValuex = (Input.GetAxisRaw("Horizontal") - oldX) / Time.deltaTime / 60;
        float deltaValuey = (Input.GetAxisRaw("Vertical") - oldY) / Time.deltaTime / 60;
        oldX = Input.GetAxisRaw("Horizontal");
        oldY = Input.GetAxisRaw("Vertical");
        float speed = Mathf.Abs(deltaValuex) + Mathf.Abs(deltaValuey);

        disherAnim.speed = speed * 10;

        if (shakeTimer < 2)
        {
            gameSquare.transform.position += Random.insideUnitSphere * speed * Time.deltaTime * 10;
            shakeTimer += Time.deltaTime;
        }
        else
        {
            shakeTimer = 0;
            gameSquare.transform.position = minigameScreenOrigPos;
        }

        disherSound.ChangeVolume(speed);
        if (Mathf.Abs(deltaValuex) < MinRotSpd && Mathf.Abs(deltaValuey) < MinRotSpd)
        {
            inputdirect = new Vector2(Input.GetAxisRaw("Horizontal"),
            Input.GetAxisRaw("Vertical"));
        }
        if (Mathf.Abs(deltaValuex) >= MinRotSpd || Mathf.Abs(deltaValuey) >= MinRotSpd)
        {
            inputdirect = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
            if (Input.GetAxisRaw("Horizontal") == inputdirect.x && Input.GetAxisRaw("Vertical") == inputdirect.y)
            {
                rotatecount += Time.deltaTime * 60;
            }
            if (rotatecount >= rotationsNeeded)
            {
                PlateClean();
            }
        }
    }

    private void PlateClean()
    {
        platesDone++;
        rotatecount = 0;
        state = State.wait;
        disherAnim.speed = 0;
        foam.playbackSpeed = 10;
        activePlate.GetComponent<SpriteRenderer>().sprite = plates[nexPlate].clean;
        activePlate.GetComponent<PlateScript>().Particles.SetActive(true);
        Score.Instance.UpdateScore(scorePerPlate);
        Destroy(dishStack.GetComponentsInChildren<Image>()[0].gameObject);
        disherSound.ChangeVolume(0);
        StartCoroutine(Wait(0.5f));
    }

    private IEnumerator Wait(float amount)
    {
        float timer = 0;
        while (timer < amount)
        {
            timer += Time.deltaTime;
            yield return null;
        }
        RemovePlate();
    }

    private void RemovePlate()
    {
        plateAnim.SetBool("nextPlate", true);
        if (platesDone >= platesTotal)
        {
            doneImage.SetActive(true);
            //miniGameParent.SetActive(false);
            Destroy(activePlate);
            DishesDoneEvent.Invoke();
        }
        else
        {
            NewPlate();
        }
    }

    private void NewPlate()
    {
        nexPlate = Random.Range(0, plates.Count);
        if (oldPlate!= null)
        {
            Destroy(oldPlate);
        }
        oldPlate = activePlate;
        activePlate = Instantiate(plates[nexPlate].dirty.gameObject, miniGameParent.transform);
        foam.playbackSpeed = 1;
        plateAnim = activePlate.GetComponent<Animator>();
        state = State.dish;
    }

    private void OnEnable()
    {
        SpawnDish();

        doneImage.SetActive(false);

        if (platesDone >= platesTotal)
        {
            Debug.Log("Done!");
            doneImage.SetActive(true);

            DishesDoneEvent.Invoke();
        }
        else if(initialized)
        {
            NewPlate();
        }
        else
        {
            initialized = true;
        }
    }

    private void SpawnDish()
    {

        for (int i = 0; i < platesToDish; i++)
        {
            Instantiate(plateUI, dishStack.transform);
            platesTotal++;
        }
        platesToDish = 0;
    }
    [ContextMenu("Add Dishes")]
    public void AddDishes(int amount = 5)
    {
        platesToDish += amount;
    }
}
