using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;


[System.Serializable]
public struct TM_AnimFrame
{
    public Sprite sprite;
    public float frametime;
}

[System.Serializable]
public class TM_SpriteAnim
{
    public string Name;
    public List<TM_AnimFrame> Frames;

}

public enum EShepAnimBehavior
{

    loop_idle = 0,
    play_once,
    play_once_and_hide,
    play_once_and_destroy,
    play_once_then_idle,

}

public class TM_SpriteAnimator : MonoBehaviour 
{
    [HideInInspector]
    public TM_SpriteAnim currentAnimation;

    public SpriteRenderer spriteRenderer;

    public EShepAnimBehavior behavior;
    public List<TM_SpriteAnim> animationList;
    public string StartAnimation;

    [Header("Audio")]
    public AudioClip clip_animStart;
    public AudioClip clip_animEnd;
    private AudioSource audioSource;

    float fTimer;
    int iFrameIndex;

    private bool bPlaying;

    public float fDelayBeforeStart;

    //Delegates on animation changes
    private List<Action<GameObject>> onAnimStartActions;
    private List<Action<GameObject>> onAnimEndActions; 

    void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        audioSource = GetComponent<AudioSource>();
    }

	// Use this for initialization
	void Start ()
	{
        fTimer = 0;
	    if (currentAnimation != null && currentAnimation.Frames != null && currentAnimation.Frames.Count > 0 )
	    {
	        fTimer = currentAnimation.Frames[0].frametime;
	    }

	    if (!string.IsNullOrEmpty(StartAnimation) && animationList != null)
	    {
	        for(int t=0; t < animationList.Count; t++)
                if( animationList[t] != null &&
                    animationList[t].Name == StartAnimation)
                    SetAnimation(animationList[t]);
	    }

	}

    public void SetAnimation( TM_SpriteAnim newAnim )
    {
        currentAnimation = newAnim;
        PlayAnim();
    }

    public void SetAnimation(string strAnimName)
    {
        if (!string.IsNullOrEmpty(strAnimName) && animationList != null)
        {
            for (int t = 0; t < animationList.Count; t++)
                if (animationList[t] != null &&
                    animationList[t].Name == strAnimName)
                {
                    SetAnimation(animationList[t]);
                    return;
                }
        }

        Debug.LogError("OH NO");
    }

    TM_SpriteAnim GetAnimByString(string strAnim)
    {
        if (!string.IsNullOrEmpty(strAnim) && animationList != null)
        {
            for (int t = 0; t < animationList.Count; t++)
                if (animationList[t] != null &&
                    animationList[t].Name == strAnim)
                    return animationList[t];
        }

        return null;
    }

    public void StartIfNotRunning(string strAnim)
    {
        //if we are playing this anim already, don't do squat
        TM_SpriteAnim maybeThis = GetAnimByString(strAnim);
        if (maybeThis == currentAnimation &&
            bPlaying)
        {
            return;
        }

        SetAnimation(strAnim);
    }
    public void PlayAnim()
    {
        if (currentAnimation != null && currentAnimation.Frames != null && currentAnimation.Frames.Count > 0)
        {
            fTimer = currentAnimation.Frames[0].frametime;
        }
        else
        {
            return;
        }

        iFrameIndex = 0;
        if (clip_animStart != null) // && audioSource != null)
        {
            TM_AudioManager.PlayClip(clip_animStart);
        }

        bPlaying = true;
        spriteRenderer.enabled = true;
        spriteRenderer.sprite = currentAnimation.Frames[0].sprite;
    }

    public void StopAnim()
    {
        bPlaying = false;
    }



	void Update () 
    {
        if (currentAnimation == null)
            return;
	    if (!bPlaying)
	        return;

        if (fDelayBeforeStart > 0f)
        {
            spriteRenderer.enabled = false;
            fDelayBeforeStart -= Time.deltaTime;
            if (fDelayBeforeStart <= 0f)
            {
                spriteRenderer.enabled = true;
            }
            return;
        }

        fTimer -= Time.deltaTime;
        if( fTimer < 0 )
        {

            iFrameIndex++;
            if (iFrameIndex >= currentAnimation.Frames.Count) // Sprites.Count)
            {
                iFrameIndex = 0;
                switch (behavior)
                {
                    case EShepAnimBehavior.loop_idle:
                        //Debug.Log("Loopy doops! " + currentAnimation.Name);
                        break;
                    case EShepAnimBehavior.play_once:
                        iFrameIndex = currentAnimation.Frames.Count - 1;
                        OnAnimEnd();
                        break;
                    case EShepAnimBehavior.play_once_and_hide:
                        spriteRenderer.enabled = false;
                        OnAnimEnd();
                        break;
                    case EShepAnimBehavior.play_once_and_destroy:
                        spriteRenderer.enabled = false;
                        bPlaying = false;
                        Destroy(gameObject,1.0f);
                        break;
                    case EShepAnimBehavior.play_once_then_idle:
                        StartIfNotRunning("idle");
                        behavior = EShepAnimBehavior.play_once_then_idle;
                        break;
                }
            }

            fTimer = currentAnimation.Frames[iFrameIndex].frametime;

            //Debug.Log( gameObject.name + " is drawing " + currentAnimation.Sprites[iFrameIndex] + " index = " + iFrameIndex + " anim = " + currentAnimation.Name );
            spriteRenderer.sprite = currentAnimation.Frames[iFrameIndex].sprite;
        }
	}

    void OnAnimEnd()
    {
        bPlaying = false;

        if (clip_animStart != null && audioSource != null)
            TM_AudioManager.PlayClip(clip_animEnd);

        if( onAnimEndActions != null )
        {
            for (int t = 0; t < onAnimEndActions.Count; t++)
            {
                Action<GameObject> a = onAnimEndActions[t];
                a(gameObject);
            }
        }
    }

    public void AddFunctionOnAnimStart(Action<GameObject> func)
    {
        AddActionToListInternal(ref onAnimStartActions, func);
    }

    public void AddFunctionOnAnimEnd(Action<GameObject> func)
    {
        Debug.Log("Adding animEnd event " + func.ToString() );
        AddActionToListInternal( ref onAnimEndActions, func);
        Debug.Log("But hey: " + onAnimEndActions.Count);
        Debug.Log("And it's: " + onAnimEndActions[0].ToString());

    }

    void AddActionToListInternal(ref List<Action<GameObject>> myList, Action<GameObject> func)
    {
        if (myList == null)
            myList = new List<Action<GameObject>>();

        if (!myList.Contains(func))
            myList.Add(func);
    }
}

