﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class AnimatorPreset : MonoBehaviour
{
    public readonly string version = "1.4";

    public Animator targetAnimator;
    float prevSpeed;
    float currentSpeed;
    bool paused = false;
    string currentAnim;

    string[] names;

    Image PauseButton;
    Color PauseButtonOriginalColor;
    Slider SpeedSlider;
    Text SpeedText;
    Slider ProgressSlider;

    Dictionary<string, StateInfo> stateCollections = new Dictionary<string, StateInfo>();

    Image TargetAnimProgress;

    public struct StateInfo
    {
        public string guid;
        public string name;
        public Image progressDisplayImage;
    }

    private void Awake()
    {
        PauseButton = transform.Find("Canvas/Control/ButtonGroup/Pause").GetComponent<Image>();
        PauseButtonOriginalColor = PauseButton.color;
        SpeedSlider = transform.Find("Canvas/Control/SpeedControl/Slider").GetComponent<Slider>();
        currentSpeed = SpeedSlider.value;
        SpeedText = transform.Find("Canvas/Control/SpeedControl/CurrentSpeed").GetComponent<Text>();
        ProgressSlider = transform.Find("Canvas/Control/ProgressControl/Slider").GetComponent<Slider>();
    }

    // Start is called before the first frame update
    void Start()
    {
        Transform template = transform.Find("Canvas/template");
        Transform grid = transform.Find("Canvas/Grid");

        RuntimeAnimatorController controller = targetAnimator.runtimeAnimatorController;

        names = new string[controller.animationClips.Length];

        for (int i = 0; i < controller.animationClips.Length; i++)
        {
            names[i] = controller.animationClips[i].name;
        }

        bool first = true;
        foreach (string name in names)
        {
            string index = Guid.NewGuid().ToString();

            GameObject g = Instantiate(template.gameObject);
            g.SetActive(true);
            g.transform.SetParent(grid);
            Button b = g.GetComponent<Button>();
            b.onClick.RemoveAllListeners();
            b.onClick.AddListener(() => SetAnim(index));
            Text t = g.transform.Find("Text").GetComponent<Text>();
            t.text = name;

            if (first) 
            { 
                TargetAnimProgress = g.transform.Find("Image").GetComponent<Image>(); 
                first = false;
            }

            stateCollections.Add(index, new StateInfo()
            {
                guid = index,
                name = name,
                progressDisplayImage = g.transform.Find("Image").GetComponent<Image>()
            });
        }
    }

    private void Update()
    {
        SpeedText.text = $"{currentSpeed.ToString("0.000")}x";
        SpeedSlider.value = currentSpeed;

        if (paused)
        {
            PauseButton.color = Color.grey;
            targetAnimator.speed = 0;
        }
        else
        {
            PauseButton.color = PauseButtonOriginalColor;
            targetAnimator.speed = currentSpeed;
        }

        if (progressUpdate)
        {
            targetAnimator.Play(currentAnim, -1, ProgressSlider.value);
            targetAnimator.speed = 0;
        } else
        {
            ProgressSlider.value = targetAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime;
            if (paused)
            {
                targetAnimator.speed = 0;
            }
            else
            {
                targetAnimator.speed = currentSpeed;
            }
        }

        TargetAnimProgress.fillAmount = targetAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime;
    }

    public void UpdateCurrentSpeed()
    {
        currentSpeed = SpeedSlider.value;
    }

    public void TogglePause()
    {
        paused = !paused;
    }

    public void ReplayAnim()
    {
        targetAnimator.Play(currentAnim, -1, 0);
    }

    public void SetAnim(string n)
    {
        StateInfo s = stateCollections[n];

        TargetAnimProgress = s.progressDisplayImage;

        currentAnim = s.name;
        targetAnimator.Play(s.name);
    }

    bool progressUpdate = false;

    public void SetProgressUpdate()
    {
        //targetAnimator.Play(currentAnim, -1, ProgressSlider.value);
    }
    public void SetProgressDown()
    {
        progressUpdate = true;
    }
    public void SetProgressUp()
    {
        progressUpdate = false;
    }
}

#if UNITY_EDITOR

[CustomEditor(typeof(AnimatorPreset))]
public class AnimatorPresetEditor : Editor
{
    AnimatorPreset animatorPreset;
    Slider speedSlider;

    public override void OnInspectorGUI()
    {
        animatorPreset = target as AnimatorPreset;
        speedSlider = animatorPreset.transform.Find("Canvas/Control/SpeedControl/Slider").GetComponent<Slider>();

        SerializedProperty targetAnimator = serializedObject.FindProperty("targetAnimator");

        EditorGUILayout.LabelField("버전", animatorPreset.version);

        GUILayout.Space(12);

        speedSlider.minValue = EditorGUILayout.FloatField("최소 속도", speedSlider.minValue);
        if (speedSlider.minValue < 0) speedSlider.minValue = 0;

        speedSlider.maxValue = EditorGUILayout.FloatField("최대 속도", speedSlider.maxValue);

        GUILayout.Space(12);

        GUILayout.Label("Camera 오브젝트에 애니메이션을 생성하고,");
        GUILayout.Label("아래 Target Animator에 Camera를 삽입");

        GUILayout.Space(12);

        EditorGUILayout.PropertyField(targetAnimator);

        GUILayout.Space(12);

        if (animatorPreset.targetAnimator != null)
        {
            RuntimeAnimatorController controller = animatorPreset.targetAnimator.runtimeAnimatorController;

            string[] stateNames = new string[controller.animationClips.Length];

            for (int i = 0; i < controller.animationClips.Length; i++)
            {
                stateNames[i] = controller.animationClips[i].name;
            }

            GUILayout.Label("인식된 애니메이션:");

            foreach (string name in stateNames)
            {
                GUILayout.Label("\t" + name);
            }
        } else
        {
            EditorGUILayout.HelpBox("카메라 Animator가 비어있습니다!", MessageType.Error);
        }

        serializedObject.ApplyModifiedProperties();
    }
}

#endif
