/*
 * File         : transitions.js
 * Created      : 20091022
 * Author       : JT Best
 * Organisation : Southstar Computers Limited
 * Copyright    : (c) 2008-11, Southstar Computers Limited
 * Purpose      : Implement a Javascript visual transition library
 * Dependencies : dom.js        [Mandatory] Southstar Library
 * Design       : fade()
 *                  Applies an attribute value step change from a start to finish value, in a total given time.
 *                fadeTo()
 *                  Fades one item out while fading new item in.
 *                registerTransitionBetweenChildren( )
 *                  Iterates through a collection of children with the given tag, transitioning to the next one.
 *                wipeRight()
 *                  Wipe from left to right over current element with new element to replace it.
 * Transitions  : We are aiming to support the following transitions.
 *                FADE{IN|OUT|TO}
 *                SLIDE{LEFT|DOWN|RIGHT|UP}
 *                SWAP
 *                WIPE{LEFT|DOWN|RIGHT|UP}
 * To Do        : Complete...
 * Changes      : NONE
 */

function fade( v_varFromElement, v_varToElement, v_strAttribute, v_intStepSize, v_intStart, v_intFinish, v_intTotalMilliseconds, v_blnHide ) {
  if ( v_intFinish != v_intStart ) {
    var objFromElement = dom.getObject( v_varFromElement );
    var objToElement = dom.getObject( v_varToElement );
    if ( objFromElement ) {
      var intDifference = v_intFinish - v_intStart;
      var intInterval = v_intTotalMilliseconds / ( intDifference / v_intStepSize );
      var strSign = ( v_intFinish > v_intStart ) ? "+" : "-";
      eval( "objToElement." + v_strAttribute + " = " + parseInt( v_intStart ) + ";" );
      objFromElement.style.zIndex = 0;
      objToElement.style.zIndex = 1;
      dom.setElementVisibility( objToElement, true );
      if ( v_blnHide ) dom.setElementVisibility( objFromElement, true );
      var idInterval =
        setInterval( function() {
                       eval( "var intTest = parseFloat( objToElement." + v_strAttribute + " ) " + strSign + "parseFloat( " + v_intStepSize + " );" );
                       switch ( strSign ) {
                         case "+":
                           if ( intTest > v_intFinish ) {
                             eval( "objToElement." + v_strAttribute + " = parseFloat( " + v_intFinish + " );" );
                             if ( v_blnHide ) dom.setElementVisibility( objFromElement, false );
                             clearInterval( idInterval );
                           } else {
                             eval( "objToElement." + v_strAttribute + " = parseFloat( objToElement." + v_strAttribute + ") + parseFloat( " + v_intStepSize + " );" );
                           }
                           break;
                           
                         case "-":
                           if ( intTest < v_intFinish ) {
                             eval( "objToElement." + v_strAttribute + " = parseFloat( " + v_intFinish + " );" );
                             clearInterval( idInterval );
                             if ( v_blnHide ) dom.setElementVisibility( objFromElement, false );
                             dom.setElementVisibility( objToElement, false );
                           } else {
                             eval( "objToElement." + v_strAttribute + " = parseFloat( objToElement." + v_strAttribute + " ) - parseFloat( " + v_intStepSize + " );" );
                           }
                           break;
                       }
                                },
                     intInterval
                   );
    }
  }
}

function fadeTo( v_varFromElement, v_varToElement, v_strAttribute, v_intStepSize, v_intStart, v_intFinish, v_intTotalMilliseconds ) {
  if ( v_intFinish != v_intStart ) {
    var objFromElement = dom.getObject( v_varFromElement );
    var objToElement = dom.getObject( v_varToElement );
    if ( objToElement ) {
      var intDifference = v_intFinish - v_intStart;
      var intInterval = v_intTotalMilliseconds / ( intDifference / v_intStepSize );
      if ( objFromElement ) {
        eval( "objFromElement." + v_strAttribute + " = " + parseInt( v_intFinish ) + ";" );
        objFromElement.style.zIndex = 0;
      }
      eval( "objToElement." + v_strAttribute + " = " + parseInt( v_intStart ) + ";" );
      dom.setElementVisibility( objToElement, true );
      objToElement.style.zIndex = 1;
      var idInterval =
        setInterval( function() {
                       eval( "var intToTest = parseFloat( objToElement." + v_strAttribute + " ) + parseFloat( " + v_intStepSize + " );" );
                       if ( objFromElement ) {
                         eval( "var intFromTest = parseFloat( objFromElement." + v_strAttribute + " ) - parseFloat( " + v_intStepSize + " );" );
                         if ( intFromTest <= v_intStart ) {
                           eval( "objFromElement." + v_strAttribute + " = parseFloat( " + v_intStart + " );" );
                           dom.setElementVisibility( objFromElement, false );
                         } else {
                           eval( "objFromElement." + v_strAttribute + " = parseFloat( objFromElement." + v_strAttribute + ") - parseFloat( " + v_intStepSize + ");" );
                         }
                       }
                       if ( intToTest >= v_intFinish ) {
                         eval( "objToElement." + v_strAttribute + " = parseFloat( " + v_intFinish + " );" );
                         clearInterval( idInterval );
                       } else {
                         eval( "objToElement." + v_strAttribute + " = parseFloat( objToElement." + v_strAttribute + ") + parseFloat( " + v_intStepSize + " );" );
                       }
                                },
                     intInterval
                   );
    }
  }
}

function juggle( v_objElement, v_intInterval, v_intBoundary ) {
  // Juggle the children (or text contents) of v_objElement by randomly shuffling elements up or down by one pixel
  // within predetermined boundaries.
  
}

function registerAnimation( v_varContainer, v_strTagname, v_intInterval, v_strTransition ) {
  var objContainer = dom.getObject( v_varContainer );
  if ( v_strTransition ) {
    switch ( v_strTransition.toUpperCase ) {
    case "JUGGLE":
      funInterval = new Function( "v_objElement", "juggle( v_objElement, 1000 )" );
      break;
    }
  }
}

function registerTransitionBetweenChildren( v_varContainer, v_strTagName, v_intInterval, v_strTransition ) {
  var objContainer = dom.getObject( v_varContainer );
  var funInitiate = new Function( "v_objElement", 
                                  "dom.setElementVisibility( v_objElement, true );"
                                );
  var funInterval = new Function();
  
  if ( v_strTransition ) {
    switch ( v_strTransition.toUpperCase() ) {
      case "FADE":
        funInterval = new Function( "v_objElement", "v_objNextElement", 
                                    "fade( v_objElement, v_objNextElement, 'style.opacity', 0.1, 0, 1, 1000, true );" );
        break;
        
      case "FADETO":
        funInterval = new Function( "v_objElement", "v_objNextElement", 
                                    "fadeTo( v_objElement, v_objNextElement, 'style.opacity', 0.1, 0, 1, 1000 );" )
        break;

      case "SLIDEDOWN":
        funInterval = new Function( "v_objElement", "v_objNextElement",
                                    "slide( v_objElement, v_objNextElement, 3000, 'DOWN' );"
                                  );
        break;
        
      case "SLIDELEFT":
        funInterval = new Function( "v_objElement", "v_objNextElement",
                                    "slide( v_objElement, v_objNextElement, 1000, 'LEFT' );"
                                  );
        break;
        
      case "SLIDERIGHT":
        funInterval = new Function( "v_objElement", "v_objNextElement",
                                    "slide( v_objElement, v_objNextElement, 1000, 'RIGHT' );"
                                  );
        break;
        
      case "SLIDEUP":
        funInterval = new Function( "v_objElement", "v_objNextElement",
                                    "slide( v_objElement, v_objNextElement, 1000, 'UP' );"
                                  );
        break;
        
      case "SWAP":
        funInterval = new Function( "v_objElement", "v_objNextElement", 
                                    "dom.setElementVisibility( v_objElement, false );" +
                                    "dom.setElementVisibility( v_objNextElement, true );"
                                  );
        break;
        
      case "WIPEDOWN":
        funInterval = new Function( "v_objElement", "v_objNextElement", 
                                    "wipe( v_objElement, v_objNextElement, 1000, 'DOWN' );"
                                  );
        break;

      case "WIPELEFT":
        funInterval = new Function( "v_objElement", "v_objNextElement", 
                                    "wipe( v_objElement, v_objNextElement, 1000, 'LEFT' );"
                                  );
        break;

      case "WIPERIGHT":
        funInterval = new Function( "v_objElement", "v_objNextElement", 
                                    "wipe( v_objElement, v_objNextElement, 1000, 'RIGHT' );"
                                  );
        break;

      case "WIPEUP":
        funInterval = new Function( "v_objElement", "v_objNextElement", 
                                    "wipe( v_objElement, v_objNextElement, 1000, 'UP' );"
                                  );
        break;
    }
  }
  if ( objContainer ) {
    
    var objElements = objContainer.getElementsByTagName( v_strTagName );
    if ( objElements && objElements.length >= 1 ) {
      funInitiate( objElements[ 0 ] );
    }
    return setInterval(
                       function () {
                         if ( objContainer ) {
                           var objElements = objContainer.getElementsByTagName( v_strTagName );
                           if ( objElements && objElements.length >= 1 ) {
                             var blnRotated = false;
                             for ( var intIndex = 0; intIndex < objElements.length; intIndex++ ) {
                               var objSibling = objElements[ intIndex ];
                               if ( objSibling.style.visibility == "visible" ) {

                                 if ( intIndex != objElements.length - 1 ) {
                                   objNextSibling = objElements[ intIndex + 1 ];
                                 } else {
                                   objNextSibling = objElements[ 0 ];
                                 }
                                 
                                 funInterval( objSibling, objNextSibling );
                                 blnRotated = true;
                                 break;
                               }
                             }
                             if ( !blnRotated ) {
                               funInterval( objElements[ objElements.length - 1 ], objElements[ 0 ] );
                             }
                           }
                         }
                       },
                       v_intInterval );
  }
}

function slide( v_varFromElement, v_varToElement, v_intTotalMilliseconds, v_strDirection ) {
  var objFromElement = dom.getObject( v_varFromElement );
  var objToElement = dom.getObject( v_varToElement );
  
  if ( objToElement ) {
    if ( objFromElement ) {
      objFromElement.style.zIndex = 0;
    }
    v_strDirection = v_strDirection.toLowerCase();
    if ( v_strDirection == "left" || v_strDirection == "right" ) {
      var numTargetSize = parseFloat( dom.getWidth( objToElement.parentNode ) );
    } else if ( v_strDirection == "up" || v_strDirection == "down" ) {
      var numTargetSize = parseFloat( dom.getHeight( objToElement.parentNode ) );
    }
    var numDelta =  numTargetSize / 20;
    var strBorder;
    var funCalcEdge, funSetEdge;
    switch ( v_strDirection ) {
      case "down":
        strBorder = "borderDown";
        objToElement.style.left = 0;
        objToElement.style.top = ( numTargetSize * -1.0 ) +"px";
        funCalcEdge = new Function( "v_objElement", "v_numDelta", "return parseFloat( dom.getTop( v_objElement ) + v_numDelta )" );
        funSetEdge = new Function( "v_objElement", "v_varValue", "v_objElement.style.top = v_varValue;" );
        funTest = new Function( "v_varValue", "return ( v_varValue >= 0 );" );
        break;
      
      case "left":
        strBorder = "borderLeft";
        objToElement.style.top = 0;
        objToElement.style.left = numTargetSize +"px";
        funCalcEdge = new Function( "v_objElement", "v_numDelta", "return parseFloat( dom.getLeft( v_objElement ) - v_numDelta )" );
        funSetEdge = new Function( "v_objElement", "v_varValue", "v_objElement.style.left = v_varValue;" );
        funTest = new Function( "v_varValue", "return ( v_varValue <= 0 );" );
        break;
      
      case "right":
        strBorder = "borderRight";
        objToElement.style.top = 0;
        objToElement.style.left = ( numTargetSize * -1.0 ) +"px";
        funCalcEdge = new Function( "v_objElement", "v_numDelta", "return parseFloat( dom.getLeft( v_objElement ) + v_numDelta )" );
        funSetEdge = new Function( "v_objElement", "v_varValue", "v_objElement.style.left = v_varValue;" );
        funTest = new Function( "v_varValue", "return ( v_varValue >= 0 );" );
        break;
      
      case "up":
        strBorder = "borderUp";
        objToElement.style.left = 0;
        objToElement.style.top = numTargetSize +"px";
        funCalcEdge = new Function( "v_objElement", "v_numDelta", "return parseFloat( dom.getTop( v_objElement ) - v_numDelta )" );
        funSetEdge = new Function( "v_objElement", "v_varValue", "v_objElement.style.top = v_varValue;" );
        funTest = new Function( "v_varValue", "return ( v_varValue <= 0 );" );
        break;
    }
    objToElement.style.opacity = 1;
    objToElement.style.zIndex = 1;
    objToElement.style[ strBorder ] = "2px solid black";
    dom.setElementVisibility( objToElement, true );
    var idInterval = setInterval( 
      function() {
        var numEdge = funCalcEdge( objToElement, numDelta );
        if ( funTest( numEdge ) ) {
          funSetEdge( objToElement, 0 );
          objToElement.style[ strBorder ] = "";
          if ( objFromElement ) dom.setElementVisibility( objFromElement, false );
          clearInterval( idInterval );
        } else {
          funSetEdge( objToElement, numEdge + "px" );
        }
      },
      v_intTotalMilliseconds / 20 );
  }
  
}

function wipe( v_varFromElement, v_varToElement, v_intTotalMilliseconds, v_strDirection ) {
  var objFromElement = dom.getObject( v_varFromElement );
  var objToElement = dom.getObject( v_varToElement );
  
  if ( objToElement ) {
    if ( objFromElement ) {
      objFromElement.style.zIndex = 0;
    }
    objToElement.style.zIndex = 0;
    v_strDirection = v_strDirection.toLowerCase();
    if ( v_strDirection == "left" || v_strDirection == "right" ) {
      var numTargetSize = parseFloat( dom.getWidth( objToElement.parentNode ) );
    } else if ( v_strDirection == "up" || v_strDirection == "down" ) {
      var numTargetSize = parseFloat( dom.getHeight( objToElement.parentNode ) );
    }
    var numDelta =  numTargetSize / 20;
    var strBorder, objToResize;
    var funCalcSize, funSetSize;
    
    switch( v_strDirection ) {
      case "down":
        objToResize = objToElement;
        objToResize.style.minHeight = 0;
        dom.setHeight( objToResize, "0px" );
        dom.setHeight( objFromElement, numTargetSize + "px" );
        strBorder = "borderBottom";
        funCalcSize = new Function( "v_objElement", "v_numDelta", "return parseFloat( dom.getHeight( v_objElement ) + v_numDelta );" );
        funSetSize = new Function( "v_objElement", "v_numSize", "dom.setHeight( v_objElement, v_numSize + 'px' );" );
        funTest = new Function( "v_numResize", "v_numMax", "v_numDelta", "return ( ( v_numMax - v_numResize ) < v_numDelta );" );
        break;
        
      case "left":
        objToResize = objFromElement;
        objToResize.style.minWidth = 0;
        dom.setWidth( objToResize, numTargetSize + "px" );
        dom.setWidth( objToElement, numTargetSize + "px" );
        strBorder = "borderRight";
        funCalcSize = new Function( "v_objElement", "v_numDelta", "return parseFloat( dom.getWidth( v_objElement ) - v_numDelta );" );
        funSetSize = new Function( "v_objElement", "v_numSize", "dom.setWidth( v_objElement, v_numSize + 'px' );" );
        funTest = new Function( "v_numResize", "v_numMax", "v_numDelta", "return ( v_numResize <= 0 );" );
        break;
        
      case "right":
        objToResize = objToElement;
        objToResize.style.minWidth = 0;
        dom.setWidth( objToResize, "0px" );
        dom.setWidth( objFromElement, numTargetSize + "px" );
        strBorder = "borderRight";
        funCalcSize = new Function( "v_objElement", "v_numDelta", "return parseFloat( dom.getWidth( v_objElement ) + v_numDelta );" );
        funSetSize = new Function( "v_objElement", "v_numSize", "dom.setWidth( v_objElement, v_numSize + 'px' );" );
        funTest = new Function( "v_numResize", "v_numMax", "v_numDelta", "return ( ( v_numMax - v_numResize < v_numDelta );" );
        break;
        
      case "up":
        objToResize = objFromElement;
        objToResize.style.minHeight = 0;
        dom.setHeight( objToResize, numTargetSize + "px" );
        dom.setHeight( objToElement, numTargetSize + "px" );
        strBorder = "borderBottom;"
        funCalcSize = new Function( "v_objElement", "v_numDelta", "return parseFloat( dom.getHeight( v_objElement ) - v_numDelta );" );
        funSetSize = new Function( "v_objElement", "v_numSize", "dom.setHeight( v_objElement, v_numSize + 'px' );" );
        funTest = new Function( "v_numResize", "v_numMax", "v_numDelta", "return ( v_numResize <= 0 );" );
        break;
    }
    objToResize.style[ strBorder ] = "2px solid black";
    objToResize.style.opacity = 1;
    objToResize.style.zIndex = 1;
    dom.setVisibility( objToElement, true );
    var idInterval = setInterval( 
      function() {
        var numResize = funCalcSize( objToResize, numDelta );
        if ( funTest( numResize, numTargetSize, numDelta ) ) {
          if ( objFromElement ) dom.setElementVisibility( objFromElement, false );
          funSetSize( objFromElement, numTargetSize + "px" );
          funSetSize( objToElement, numTargetSize + "px" );
          objToElement.style[ strBorder ] = "";
          clearInterval( idInterval );
        } else {
          funSetSize( objToResize, numResize );
        }
      },
      v_intTotalMilliseconds / 10 );
  }
}

function wipeDown( v_varFromElement, v_varToElement, v_intTotalMilliseconds ) {
  var objFromElement = dom.getObject( v_varFromElement );
  var objToElement = dom.getObject( v_varToElement );
  
  if ( objToElement ) {
    if ( objFromElement ) {
      objFromElement.style.zIndex = 0;
    }
    objToElement.style.minHeight = 0;
    objToElement.style.borderBottom = "2px solid black";
    objToElement.style.opacity = 1;
    objToElement.style.zIndex = 1;
    dom.setHeight( objToElement, 0 );
    var numTargetHeight = parseFloat( dom.getHeight( objToElement.parentNode ) );
    var intDeltaHeight =  numTargetHeight / 10;
    dom.setElementVisibility( objToElement, true );
    var idInterval = setInterval( 
      function() {
        var numToElementHeight = dom.getHeight( objToElement );
        dom.setHeight( objToElement,  parseFloat( numToElementHeight + intDeltaHeight ) + "px" );
        if ( ( numTargetHeight - parseFloat( numToElementHeight + intDeltaHeight ) ) < intDeltaHeight ) {
          dom.setHeight( objToElement,  numTargetHeight + "px" );
          objToElement.style.borderBottom = "";
          if ( objFromElement ) dom.setElementVisibility( objFromElement, false );
          clearInterval( idInterval );
        }
      },
      v_intTotalMilliseconds / 10 );
  }
}

function wipeRight( v_varFromElement, v_varToElement, v_intTotalMilliseconds ) {
  var objFromElement = dom.getObject( v_varFromElement );
  var objToElement = dom.getObject( v_varToElement );
  
  if ( objToElement ) {
    if ( objFromElement ) {
      objFromElement.style.zIndex = 0;
    }
    objToElement.style.minWidth = 0;
    objToElement.style.borderRight = "2px solid black";
    objToElement.style.opacity = 1;
    objToElement.style.zIndex = 1;
    dom.setWidth( objToElement, 0 );
    var numTargetWidth = parseFloat( dom.getWidth( objToElement.parentNode ) );
    var intDeltaWidth =  numTargetWidth / 10;
    dom.setElementVisibility( objToElement, true );
    var idInterval = setInterval( 
      function() {
        var numToElementWidth = dom.getWidth( objToElement );
        dom.setWidth( objToElement,  parseFloat( numToElementWidth + intDeltaWidth ) + "px" );
        if ( ( numTargetWidth - parseFloat( numToElementWidth + intDeltaWidth ) ) < intDeltaWidth ) {
          dom.setWidth( objToElement,  numTargetWidth + "px" );
          objToElement.style.borderRight = "";
          if ( objFromElement ) dom.setElementVisibility( objFromElement, false );
          clearInterval( idInterval );
        }
      },
      v_intTotalMilliseconds / 10 );
  }
}


