/* {{{ GPL
  
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  
}}} */
  
var Animation = Class.extend({
    
  // {{{ init
  init: function( width, height ) {
    
    this.log.debug( "Created animation",  width, height );
    this.figures = [];
    this.frames = [];

    this.width = width;
    this.height = height;
          
    this.backgroundColor = new Color( 255, 255, 255 );
    this.frameDuration = 200; // milliseconds;
          
    this.saved = false;
    this.history = new History( this );
    this.listeners = [];

    this.currentFrameNumber = -1;
    this.currentFrame = null;

    this.pageName = "unknown.flick";
    this.largestFigureId = 0;
    
  },
  // }}}
  
  // {{{ allocateNextFigureId
  allocateNextFigureId: function() {
    this.largestFigureId ++;
    return this.largestFigureId;
  },
  // }}}
  
  // {{{ usedFigureId
  usedFigureId: function( id ) {
    if ( this.largestFigureId < id ) {
      this.largestFigureId = id;
    }
  },
  // }}}
  
  // {{{ revert
  revert: function( animation ) {
    // Called when an animation is loaded, the existing Animation object is reused, so that we don't need to
    // set all of the listeners, the global variables and the 'animation' attributes of the various views
    // and controllers.

    this.figures = animation.figures;
    for ( var i = 0; i < animation.frames.length; i ++ ) {
      this.addFrame( animation.frames[ i ].copy(), i );
    }
    // this.frames = animation.frames;
    this.width = animation.width;
    this.height = animation.height;
    this.backgroundColor = animation.backgroundColor;
    this.frameDuration = animation.frameDuration;
    this.saved = true;
    this.history = new History( this );
    this.currentFrameNumber = animation.currentFrameNumber;
    this.currentFrame = this.frames[ this.currentFrameNumber ];
    this.pageName = animation.pageName;
    
    this.notifyMajorChange();
  },
  // }}}
  
  // {{{ addFrame
  addFrame: function( frame, position ) {
    
    this.log.debug( "Adding frame", frame, this );
    frame.addedTo( this );
    
    if ( position != null ) {
      this.frames.splice( position, 0, frame );
      this.notifyFrameAdded( position + 1 ); 
    } else {
      this.frames[ this.frames.length ] = frame;
      this.notifyFrameAdded( this.frames.length - 1 ); 
    }
    
    if ( this.frames.length == 1 ) {
      this.currentFrameNumber = 0;
      this.currentFrame = this.frames[ 0 ];
    }
    
  },
  // }}}

  // {{{ removeFrame
  removeFrame: function( frameNumber ) {
    
    this.frames.splice( frameNumber, 1 );
    if ( this.currentFrameNumber == frameNumber ) {
      if ( this.currentFrameNumber > 0 ) {
        this.setCurrentFrameNumber( this.currentFrameNumber - 1 );
      } else {
        this.setCurrentFrameNumber( 0 );
      }
    }
    
    this.notifyFrameRemoved( frameNumber );
  },
  // }}}
  
  // {{{ getCurrentFrame
  getCurrentFrame: function() {
    return this.currentFrame;
  },
  // }}}
  
  // {{{ getCurrentFrameNumber
  getCurrentFrameNumber: function() {
    return this.currentFrameNumber;
  },
  // }}}
  
  // {{{ setCurrentFrameNumber
  setCurrentFrameNumber: function( frameNumber ) {
    
    var old = this.currentFrameNumber;
    if ( old == frameNumber ) {
      return;
    }
    
    if ( (frameNumber < 0) || (frameNumber >= this.frames.length) ) {
      this.log.error( "Frame Number out of range", frameNumber, this.frames.length );
      return;
    }
    
    this.currentFrame = this.frames[ frameNumber ];
    this.currentFrameNumber = frameNumber;

    this.notifyFrameChange( old, this.currentFrameNumber );
  },
  // }}}
    
  // {{{ addListener
  addListener: function( listener ) {
    this.listeners[ this.listeners.length ] = listener;
  },
  // }}}
  
  // {{{ notifyFrameChanged
  notifyFrameChanged: function() {
    this.log.debug( "Notifying listeners about a changed frame." );
    for ( var i = 0; i < this.listeners.length; i ++ ) {
      if ( this.listeners[ i ].onFrameChanged != null ) {
        this.listeners[ i ].onFrameChanged( this.getCurrentFrameNumber() );
      }
    }
  },
  // }}}

  // {{{ notifyFrameChange
  notifyFrameChange: function( oldFrameNumber, newFrameNumber ) {
    this.log.debug( "Notifying listeners that we've moved to a different frame" );
    for ( var i = 0; i < this.listeners.length; i ++ ) {
      if ( this.listeners[ i ].onFrameChange != null ) {
        this.listeners[ i ].onFrameChange( oldFrameNumber, newFrameNumber );
      }
    }
  },
  // }}}
  
  // {{{ notifyFrameAdded
  notifyFrameAdded: function( frameNumber ) {
    for ( var i = 0; i < this.listeners.length; i ++ ) {
      if ( this.listeners[ i ].onFrameAdded != null ) {
        this.listeners[ i ].onFrameAdded( frameNumber );
      }
    }
  },
  // }}}

  // {{{ notifyFrameRemoved
  notifyFrameRemoved: function( frameNumber ) {
    for ( var i = 0; i < this.listeners.length; i ++ ) {
      if ( this.listeners[ i ].onFrameRemoved != null ) {
        this.listeners[ i ].onFrameRemoved( frameNumber );
      }
    }
  },
  // }}}
  
  // {{{ notifyMajorChange
  notifyMajorChange: function() {
    for ( var i = 0; i < this.listeners.length; i ++ ) {
      if ( this.listeners[ i ].onMajorChange != null ) {
        this.listeners[ i ].onMajorChange();
      }
    }
  },
  // }}}
  
  // {{{ toString
  toString: function() {
    return "Animation";
  }
  // }}}

});


Animation.prototype.log = new Log( "Animation" );

