using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UGCTools.Runtime;
using System;
using UnityEngine.Networking;

public class UGCWebImpoter : MonoBehaviour
{
    public enum PLAYSTATE
    {
        Playing,
        Paused,
        Stopped
    }
    public enum PLAYMODE
    {
        Loop,
        Once
    }
    private string assetPath;
    private UGCContextConfig config;
    private PLAYSTATE playState = PLAYSTATE.Stopped;
    private PLAYMODE playMode = PLAYMODE.Once;
    private float loadProgress = 0.0f;
    private float musicTimeline = 0;

    public Animator Animator;
    public AudioSource AudioSource;
    public Action<PLAYSTATE> StateChangeEvent;

    public string AssetPath
    {
        get
        {
            return assetPath;
        }
        set
        {
            assetPath = value;
        }
    }

    public UGCContextConfig Config
    {
        get
        {
            return config;
        }
    }

    public PLAYSTATE PlayState
    {
        get
        {
            return playState;
        }
    }

    public PLAYMODE PlayMode
    {
        get
        {
            return playMode;
        }
    }

    private static UGCWebImpoter _instance;
    public static UGCWebImpoter Instance
    {
        get
        {
            return _instance;
        }
    }

    private void OnEnable()
    {
        _instance = this;
    }

    private void Start()
    {
        //string urlTest = "file://" + "C:\\Users\\ralph\\AppData\\LocalLow\\Eden\\DanceEden\\Contexts\\Queencard";
        //LoadUGCContextConfig(urlTest, (contextConfig) =>
        //{
        //    Debug.Log("contextConfig: " + contextConfig);
        //});
    }

    public void LoadUGCContextConfig(string url, Action<UGCContextConfig> callback)
    {
        string contextConfigInfoPath = url + "/info.bytes";
        StartCoroutine(LoadContextConfigAsyn(contextConfigInfoPath, callback));
    }

    private IEnumerator LoadContextConfigAsyn(string url, Action<UGCContextConfig> callback)
    {
        using(UnityWebRequest request = UnityWebRequest.Get(url))
        {
            yield return request.SendWebRequest();
            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError(request.error);
                callback(null);
            }
            else
            {
                byte[] data = request.downloadHandler.data;
                string json = System.Text.Encoding.UTF8.GetString(SimpleEncryptor.Decrypt(data));
                UGCContextConfig contextConfig = JsonUtility.FromJson<UGCContextConfig>(json);
                callback(contextConfig);
            }
        }
    }

    public void LoadAnimatinoAsync(string url, Action<AnimationClip> callback, Action<float> progressCallback)
    {
        AssetBundlesManager.Instance.LoadAssetBundleAsync<AnimationClip>(url, callback, progressCallback);
    }

    public void LoadAudioClipAsync(string url, Action<AudioClip> callback, Action<float> progressCallback)
    {
        AssetBundlesManager.Instance.LoadAssetBundleAsync<AudioClip>(url, callback, progressCallback);
    }

    public void Play(string url, Action<AnimationClip> animationCallback, Action<AudioClip> audioCallback, Action<float> progressCallback = null)
    {
        if(this.Animator != null)
            this.Animator.SetBool("dancing", false);
        loadProgress = 0;
        float animationLoadProgress = 0;
        float audioLoadProgress = 0;
        LoadUGCContextConfig(url, (contextConfig) =>
        {
            string platform = "/WebGL";
#if UNITY_EDITOR
            platform = "/StandaloneWindows";
#endif
            if (contextConfig != null)
            {
                config = contextConfig;
                string animationUrl = url + platform + $"/animation_{contextConfig.animationContext.hashCode}_{contextConfig.timeStamp}.ab";
                LoadAnimatinoAsync(animationUrl, animationCallback, (progress) =>
                {
                    animationLoadProgress = progress;
                    loadProgress = (animationLoadProgress + audioLoadProgress) / 2;
                    progressCallback?.Invoke(loadProgress);
                    Debug.Log("progress: " + progress);
                });

                string audioUrl = url + platform + $"/audio_{contextConfig.audioContext.hashCode}_{contextConfig.timeStamp}.ab";
                LoadAudioClipAsync(audioUrl, audioCallback, (progress) =>
                {
                    audioLoadProgress = progress;
                    loadProgress = (animationLoadProgress + audioLoadProgress) / 2;
                    progressCallback?.Invoke(loadProgress);
                    Debug.Log("progress: " + progress);
                });
            }
        });
    }

    public void Pause()
    {
        SetPlayState(PLAYSTATE.Paused);
        if (AudioSource != null)
        {
            AudioSource.Pause();
        }
        if (Animator != null)
        {
            Animator.speed = 0;
        }
    }

    public void Stop()
    {
        SetPlayState(PLAYSTATE.Stopped);
        if (AudioSource != null)
        {
            AudioSource.Stop();
        }
        if (Animator != null)
        {
            Animator.SetBool("dancing", false);
            Animator.speed = 1;
        }
    }

    public void Resume()
    {
        SetPlayState(PLAYSTATE.Playing);
        if (AudioSource != null)
        {
            AudioSource.time = musicTimeline;
            AudioSource.Play();
        }
        if (Animator != null)
        {
            Animator.speed = 1;
            float actionStartTime = config.audioContext.musicStartTime;
            float audioTimeline = AudioSource.time;
            if (actionStartTime <= audioTimeline && !Animator.GetBool(""))
            {
                Animator.SetBool("dancing", true);
            }
        }
    }

    public void SetPlayState(PLAYSTATE state)
    {
        if (state == PLAYSTATE.Paused)
            musicTimeline = AudioSource.time;
        else if(state == PLAYSTATE.Stopped)
            musicTimeline = 0;
        playState = state;
        StateChangeEvent?.Invoke(state);
    }

    public void Update()
    {
        if (playState == PLAYSTATE.Playing)
        {
            float actionStartTime = config.audioContext.musicStartTime;
            float audioTimeline = AudioSource.time;
            if (actionStartTime <= audioTimeline && !Animator.GetBool("dancing"))
            {
                Animator.speed = 1;
                Animator.SetBool("dancing", true);
            }
            if (audioTimeline >= config.audioContext.musicLength)
            {
                Stop();
            }
        }
        if (Animator != null)
        {
            AnimatorStateInfo stateInfo = Animator.GetCurrentAnimatorStateInfo(0);
            if (stateInfo.IsName("dance") && stateInfo.normalizedTime >= 1.0f)
            {
                Animator.SetBool("dancing", false);
                AudioSource.Stop();
                SetPlayState(PLAYSTATE.Stopped);
                if (playMode == PLAYMODE.Loop)
                {
                    AudioSource.time = musicTimeline;
                    AudioSource.Play();
                    SetPlayState(PLAYSTATE.Playing);
                }
            }
        }
    }
}
