#include "AnimatedToon.h"

AnimatedToon::AnimatedToon ()
{
  refCount=0;
  animations.clear();
}

AnimatedToon::~AnimatedToon ()
{
}

void AnimatedToon::incRefCount ()
{
  if (refCount < 2 ^ 32)
    refCount ++;
}

void AnimatedToon::decRefCount ()
{
  if (refCount > 0)
    refCount --;
}

uint32_t AnimatedToon::getRefCount ()
{
  return refCount;
}

bool AnimatedToon::addAnimation (const string & keyName, AnimatedAnimation & anim)
{
  //reject an animation with the same name already exists.
  if (keyName.empty() || keyName == "NULL_INDEX")
    return false;

  map <string, AnimatedAnimation> :: iterator iter2;
  iter2 = animations.find (keyName);

  if (iter2 == animations.end())
    {
      animations[keyName]=anim;
      return true;
    }
  else
    return false;
}

void AnimatedToon::getNext(Param & hash, AffineTransformationMatrix & atm,
                           AudioTransformation & at, AnimatedState & as)
{
  if (!animationNameExists(as.getAnimation()))
    return;

  int tim;
  hash.getInt("Time Right Now", tim);

  map <string, AnimatedAnimation> :: iterator iter2 = getAnimation(as.getAnimation());

  if (as.getAnimationStatus()==ANIMATION_STATUS_STOP)
    {
      //just return
      //-->tell animation to ignore the sound.<--
      hash.setInt("Time Right Now", 0);
      hash.setBool("Do not play sound", true);
      iter2->second.get (hash, atm, as, at);
      return;
    }
  else if (as.getAnimationStatus()==ANIMATION_STATUS_PAUSE)
    {
      //Do not add to total running time
      //get next frame
      //set last time was called to now

      hash.setBool("Do not play sound", true);
      hash.setInt("Time Right Now", as.getTotalRunningTime());
      iter2->second.get (hash, atm, as, at);
      as.setLastTimeAnimated(tim);
      return;
    }
  else if (as.getAnimationStatus()==ANIMATION_STATUS_PLAY)
    {
      //when getNextFrame
      //if last call was play, add (timeGiven - last time was called) to total running time
      //set last time was called to now

      if (as.getPreviousAnimationStatus()==ANIMATION_STATUS_PLAY)
        {
          if (int(as.getLastTimeAnimated())<=tim)
            as.addToTotalRunningTime (tim-as.getLastTimeAnimated());
        }
      else
        as.play(); //Set previous state to play.

      hash.setBool("Do not play sound", true);
      hash.setInt("Time Right Now", as.getTotalRunningTime());
      iter2->second.get (hash, atm, as, at);
      as.setLastTimeAnimated(tim);
      return;
    }
}

int AnimatedToon::numberOfAnimations ()
{
  return animations.size();
}

//adds the name of all graphic frames into the vector.
void AnimatedToon::getAllGraphicFrames (vector <string> & ans)
{
  map <string, AnimatedAnimation> :: iterator animationIterator;

  animationIterator=animations.begin();
  while (animationIterator!=animations.end())
    {
      animationIterator->second.getAllGraphicFrames(ans);
      animationIterator++;
    }
}

void AnimatedToon::getAllAudioBuffers (vector <string> & ans)
{
  map <string, AnimatedAnimation> :: iterator animationIterator;

  animationIterator=animations.begin();
  while (animationIterator!=animations.end())
    {
      animationIterator->second.getAllAudioBuffers(ans);
      animationIterator++;
    }
}

void AnimatedToon::getAllAnimationNames (vector <string> & ans)
{
  map <string, AnimatedAnimation> :: iterator animationIterator;

  animationIterator=animations.begin();
  while (animationIterator!=animations.end())
    {
      ans.push_back(animationIterator->first);
      animationIterator++;
    }
}

bool AnimatedToon::animationNameExists (const string & animName)
{
  //returns true if there exists an animation with this name.
  return !(getAnimation(animName)==animations.end());
}

int AnimatedToon::getAnimationDuration (const string & animName)
{
  //returns duration of animation or -1 if it doesn't exist.
  if (!animationNameExists(animName))
    return -1;
  else
    return getAnimation(animName)->second.getDuration();
}

map <string, AnimatedAnimation> :: iterator AnimatedToon::getAnimation (const string & animName)
{
  return animations.find (animName);
}
