using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;

namespace Rokojori
{  
  public interface Animator
  {
    public void OnAnimatorStart();
    public void OnAnimatorEnd();
    public void OnAnimatorCancel();
  }

  /*
    public void OnAnimatorStart(){}
    public void OnAnimatorEnd(){}
    public void OnAnimatorCancel(){}
  */

  public class AnimationMember
  {
    public static readonly AnimationMember Position = new AnimationMember( "position" );
    public static readonly AnimationMember Rotation = new AnimationMember( "rotation" );
    public static readonly AnimationMember Scale    = new AnimationMember( "scale" );

    public static readonly AnimationMember[] Transform = new AnimationMember[]
    {
      AnimationMember.Position,  AnimationMember.Rotation,  AnimationMember.Scale
    };

    string _name;
    public string name => _name;

    public AnimationMember( string name )
    {
      _name = name;
    }
  }
  
  public class AnimationManager
  {     
    static MultiMap<Node,string,Animator> _animating = new MultiMap<Node,string,Animator>();



    public static Animator GetAnimator( Node node, AnimationMember member  )
    {
      return _animating.Get( node, member.name );
    }

    public static bool IsAnimating( Animator animator, Node node, AnimationMember member )
    { 
      return GetAnimator( node, member ) == animator;
    }    

    public static bool IsAnimating( Animator animator, Node node, params AnimationMember[] members )
    { 
      for ( int i = 0; i < members.Length; i++ )
      {
        if ( ! IsAnimating( animator, node, members[ i ] ) )
        {
          return false;
        }
      }

      return members.Length > 0;
    }

    public static bool IsAnimating( Animator animator, Node[] nodes, params AnimationMember[] members )
    { 
      for ( int i = 0; i < nodes.Length; i++ )
      {
        if ( ! IsAnimating( animator, nodes[ i ], members ) )
        {
          return false;
        }
      }

      return nodes.Length > 0;
    }

    public static void StartAnimation( Animator animator, Node node, AnimationMember member )
    {
      var activeAnimator = GetAnimator( node, member );
      
      if ( activeAnimator != null )
      {
        activeAnimator.OnAnimatorCancel();
      }

      _animating.Set( node, member.name, animator );

    }

    public static void StartAnimation( Animator animator, Node node, params AnimationMember[] members )
    {
      for ( int i = 0; i < members.Length; i++ )
      {
        StartAnimation( animator, node, members[ i ] );
      }
    }

    public static void StartAnimation( Animator animator, Node[] nodes, params AnimationMember[] members )
    {
      for ( int i = 0; i < nodes.Length; i++ )
      {
        StartAnimation( animator, nodes[ i ], members );
      }
    }

    public static void EndAnimation( Animator animator, Node node, AnimationMember member )
    {
      var activeAnimator = GetAnimator( node, member );
      
      if ( activeAnimator != null )
      {
        activeAnimator.OnAnimatorCancel();
      }
    } 

    public static void EndAnimation( Animator animator, Node node, params AnimationMember[] members )
    {
      for ( int i = 0; i < members.Length; i++ )
      {
        EndAnimation( animator, node, members[ i ] );
      }
    }

    public static void EndAnimation( Animator animator, Node[] nodes, params AnimationMember[] members )
    {
      for ( int i = 0; i < nodes.Length; i++ )
      {
        EndAnimation( animator, nodes[ i ], members );
      }
    }
  }
}