//++
// ToggleStateChain.class.js
// ToggleState and ToggleChain objects.
// Author(s): Chris Olive
// DoublePrime LLC
// April 29, 2007
//--

// ToggleState Object _________________________________________________________

function ToggleState( object, initialEvent, alternateEvent, setInitialState ) {

   var class = {

      // Private properties.

      __object         : object,
      __initialEvent   : typeof initialEvent   == 'function' ? initialEvent   : function () { return false },
      __alternateEvent : typeof alternateEvent == 'function' ? alternateEvent : function () { return false },
      __state          : true,

      // Public methods.

      // Method: Toggle
      // Toggle state.  Toggle state toggles the state and executes the event
      // associated with that state.
      
      toggle : function () {
      
         // Toggle state.
      
         this.__state = !this.__state;
      
         // Run proper state.  The function associated with the event CAN send back
         // a function result if necessary.
      
         if (this.__state) return this.__initialEvent( this.__object );
         if (this.__alternateEvent == null) return this.__initialEvent( this.object );
         return this.__alternateEvent( this.__object );
      
      },
            
      // Method: Is Initial State
      // Returns true if the current toggle state is in the initial state.  False
      // otherwise.
      
      isInitialState : function () { return this.__state },
      
      // Method: Set Initial State
      // Explicitly sets the initial toggle state to be on (ie. "on" state)
      
      setInitialState : function () {
         this.__state = true;
         return this.__initialEvent( this.__object );
      },
      
      // Method: Set Alternate State
      // Explicitly sets the alternate toggle state or the "off" state.
      
      setAlternateState : function () {
         this.__state = false;
         if (this.__alternateEvent == null) return this.__initialEvent( this.__object );
         return this.__alternateEvent( this.__object );
      }

   };

   // Add class to instance.

   for (var element in class) this[element] = class[element];

   // Add TS instance to object self and set initial state.

   object.toggleState = this;                // Add TS instance to object self
   if (setInitialState || setInitialState == null)
      this.setInitialState();                // Set initial toggle state

}


// ToggleChain Object _________________________________________________________

function ToggleChain() {

   var class = {

      // Private properties.

      __chain : [],

      // Public methods.

      // Method: Execute
      // This the "meat and potatoes" method -- executes all the ToggleStates in the
      // ToggleChain.
      
      execute : function () {
         for (var i=0; i<this.__chain.length; i++)
            this.__chain[i].toggleState.toggle();
      },
      
      // Method: Set Initial State
      // Sets all the ToggleStates in the ToggleChain to the initial state (on state).
      
      setInitialState : function () {
         for (var i=0; i<this.__chain.length; i++)
            this.__chain[i].toggleState.setInitialState();
      },
      
      // Method: Set Alternate State
      // Sets all the ToggleStates in the ToggleChain to the alternate state (off state).
      
      setAlternateState : function () {
         for (var i=0; i<this.__chain.length; i++)
            this.__chain[i].toggleState.setAlternateState();
      },
      
      // Method: Push
      // Pushes another object with an embedded ToggleState into the existing
      // ToggleChain (pushes to end of chain).
      
      push : function ( ts ) { if (ts.toggleState) this.__chain.push( ts ) },
            
      // Method: Pop
      // Pops another object out of the existing ToggleChain (pops from end of chain).
      
      pop : function () {
         if (this.__chain.length) {
            return this.__chain.pop();
         } else {
            return null;
         }
      },
      
      // Method: Unshift
      // Unshifts onother object with an embedded ToggleState intot the existing
      // ToggleChain (unshifts to beginning of chain).
      
      unshift : function ( ts ) { if (ts.toggleState) this.__chain.unshift( ts ) },

      // Method: Shift
      // Shifts another object out of the existing ToggleChain (shifts from beginning
      // of chain).
      
      shift : function () {
         if (this.__chain.length) {
            return this.__chain.shift();
         } else {
            return null;
         }
      }
      
   };

   // Add class to instance.

   for (var element in class) this[element] = class[element];

   // Add all objects which are arguments to the ToggleChain.

   for (var i=0; i<arguments.length; i++) this.push( arguments[i] );

}

