/****************************************************************************
 * Copyright (c) 1998-2007 Luna Imaging, Inc.  All Rights Reserved.
 *
 * This software is confidential and proprietary information of
 * Luna Imaging, Inc.  ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Luna Imaging, Inc.
 *
 * The software may not be copied, reproduced, translated or reduced to
 * any electronic medium or machine-readable form without
 * the prior written consent of Luna Imaging.
 *
 * You are not allowed to distribute the binary and source code
 * (if released) to third parties, without the prior written consent from
 * Luna Imaging.
 *
 * You are not allowed to reverse engineer, disassemble or decompile
 * code, or make any modifications of the binary or source code, remove
 * or alter any trademark, logo, copyright or other proprietary notices,
 * legends, symbols, or labels in the Software.
 *
 * You are not allowed to sub-license the Software or any derivative
 * work based on or derived from the Software.
 *
 * LUNA IMAGING MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
 * A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, LUNA IMAGING SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, 
 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *   
 *  cruiz10020@yahoo.com
 * 
 *  ThumbnailPanner.js
 * 
 *  Description:
 *    Descriptive Information for an image panel
 *
 *  Structure:
 *
 *
 *  Requires:
 *    prototype.js - http://www.prototypejs.org/
 *
 *  Development History:
 *    5-14-2007       - created
 *
*******************************************************************************/



function ThumbnailPanner()
{
  this.mContainer = null;
  this.mPanel = null;
  this.mBody = null;
  this.mPanBox = null;
  this.mGlassPlate = null;
  
  this.mImagePanel = null;
  this.mIsHidden = false;
  this.mAnimate = true;
  this.mCurrentAction = null;
  this.mActionInProgress = null;
  
  this.ACTION_PAN = 'ACTION_PAN';
  this.ACTION_MOVE = 'ACTION_MOVE';
  this.ACTION_DEFAULT = this.ACTION_MOVE;
  
  this.MARGIN = 14;
  this.DEFAULT_SIZE = [120, 120];
  
  this.CLASSNAME = 'thumbnailPanner';
  this.PAN_BOX_CLASSNAME = 'panBox';
  this.THUMBNAIL_INSTRCUTIONS = 'Drag from the edges to move around!';
  this.PAN_BOX_INSTRCUTIONS = 'Drag around to pan!';
  
  
  this.init = function()
  {
    this.mPanel = $( document.createElement( 'div' ) );
    this.mBody = $( document.createElement( 'img' ) );
    this.mPanBox = $( document.createElement( 'div' ) );
    this.mGlassPlate = $( document.createElement( 'div' ) );
    
    //this.mPanel.appendChild( this.mPanBox );
    this.mPanel.appendChild( this.mBody );
    this.mContainer.appendChild( this.mPanBox );
    this.mContainer.appendChild( this.mPanel );
    this.mContainer.appendChild( this.mGlassPlate );
    
    this.mPanel.addClassName( this.CLASSNAME );
    this.mPanBox.addClassName( this.PAN_BOX_CLASSNAME );
    
    this.mPanel.title = this.THUMBNAIL_INSTRCUTIONS;
    this.mPanBox.title = this.PAN_BOX_INSTRCUTIONS;    
    
    this.mPanel.thumbnailPanner = this;
    this.mBody.thumbnailPanner = this;
    this.mPanBox.thumbnailPanner = this;
    this.mGlassPlate.thumbnailPanner = this;
    
    // events
    var tp = this;    
    this.mPanel.onmousedown = Static_ThumbnailPanner_StartMove;    
    this.mPanBox.onmousedown = Static_ThumbnailPanner_StartMove;
    this.mPanBox.onmouseover = function(){ tp.setCurrentAction( tp.ACTION_PAN ); };
    this.mPanBox.onmouseout = function(){ tp.setCurrentAction( null ); };
    
    // stylings
    this.mPanel.style.position = 'absolute';
    this.mPanel.style.top = 0 + 'px';
    this.mPanel.style.left = 0 + 'px';
    this.mPanel.style.overflow = 'hidden';
    this.mPanel.style.zIndex = 8888;
    this.mPanel.style.cursor = 'move';
    
    this.mBody.style.position = 'absolute';
    this.mBody.style.top = this.MARGIN + 'px';
    this.mBody.style.left = this.MARGIN + 'px';
    
    this.mPanBox.style.position = 'absolute';
    this.mPanBox.style.top = 0 + 'px';
    this.mPanBox.style.left = 0 + 'px';
    this.mPanBox.style.zIndex = 8999;
    
    jshSetOpacity( this.mPanBox, .4 );
    
    var margin = 10;
    var screenSize = jshGetWindowSize();
    var offset = [0,0];//Position.page( this.mContainer );
    this.mGlassPlate.hide();
    this.mGlassPlate.style.position = 'absolute';
    this.mGlassPlate.style.left = ( offset[0] ) + 'px';
    this.mGlassPlate.style.top = ( offset[1] ) + 'px';
    this.mGlassPlate.style.width = ( screenSize[0] ) + 'px';
    this.mGlassPlate.style.height = ( screenSize[1]  ) + 'px';
    this.mGlassPlate.style.zIndex = 99999;
    this.mGlassPlate.style.backgroundColor = 'black';
    jshSetOpacity( this.mGlassPlate, .02 );
    
    
    this.resize();
    this.moveToDefaultPosition();
    this.updatePanBox();
    this.mPanel.hide();
    this.mPanBox.hide();
    this.hide();
    this.setCurrentAction( this.ACTION_DEFAULT );
  };
  
  this.render = function( container )
  {
    if( container )
    {
      this.mContainer = container;
      this.init();
    }
  };
  
  this.update = function()
  {    
    if( this.mImagePanel && this.mImagePanel.mediaInfo )
    {     
      if( this.mImagePanel.mediaInfo.urlSize0 != this.mBody.src )
      {
        // lets fetch the image. 
        var tp = this;
        this.mBody.onload = function(){ tp.resize(); tp.updatePanBox(); };
        this.mBody.src = this.mImagePanel.mediaInfo.urlSize0;
      }
      
      // update the panning box
      this.updatePanBox();
    }
    else
    {
      this.mBody.src = null;
      this.mBody.hide();
      this.mPanBox.hide();
      this.resize();
    }
    
  };
  
  this.updatePanBox = function( forceUpdate )
  {
    if( ( forceUpdate == true ) || 
        ( this.mIsHidden == false ) )
    {
      var width = this.DEFAULT_SIZE[0];
      var height = this.DEFAULT_SIZE[1];
      
      var panX = null;
      var panY = null;
      if( this.mImagePanel && this.mBody.width && this.mBody.height )
      {
        // make sure we are the right size;
        this.resize();
        
        // lets show the panning box      
        var size = this.mImagePanel.getCurrentImageSize();
        var panelDimensions = this.mImagePanel.getDimensions();
        var ratio = [ ( panelDimensions[0] / size[0] ), ( panelDimensions[1] / size[1] ) ];        
        var translatedDimensions = [ Math.round( ratio[0] * this.mBody.width ), Math.round( ratio[1] * this.mBody.height ) ];
        
        var currentViewPoint = this.mImagePanel.getActualViewPoint();
        ratio = [ ( currentViewPoint[0] / size[0] ), ( currentViewPoint[1] / size[1] ) ];
        var translatedViewPoint = [ Math.round( ratio[0] * this.mBody.width ), Math.round( ratio[1] * this.mBody.height ) ];        
        
        // make sure they are no larger than the image its self
        translatedDimensions[0] = Math.min( this.mBody.width, translatedDimensions[0] );
        translatedDimensions[1] = Math.min( this.mBody.height, translatedDimensions[1] );
        
        width = translatedDimensions[0];
        height = translatedDimensions[1];
        
        
        var borderWidth = parseInt( this.mPanBox.getStyle( 'borderLeftWidth' ) );
        var borderHeight = parseInt( this.mPanBox.getStyle( 'borderTopWidth' ) );
        var offset = [ this.MARGIN, this.MARGIN ];
        panX = offset[0] + borderWidth;
        if( width < this.mBody.width )
        {
          panX += translatedViewPoint[0];
        }
          
        panY = offset[1] + borderHeight;        
        if( height < this.mBody.height )
        {
          panY += translatedViewPoint[1];
        }
        
        /*
        debug(
          'size: ', size, '\n',
          'panelDimensions: ', panelDimensions, '\n',
          'ratio: ', ratio, '\n',
          'currentViewPoint: ', currentViewPoint, '\n',
          'translatedViewPoint: ', translatedViewPoint, '\n',
          'translatedDimensions: ', translatedDimensions, '\n',
          'mImage: ', this.mImage.width, ', ', this.mImage.height
        );
        */ 
                
        // invert for css coordinates
        translatedViewPoint[0] *= -1;
        translatedViewPoint[1] *= -1;
      }
      else
      {
        // image not yet loaded
        //alert( 'image not yet loaded' );
      }
      
      // we are only seeing a porition so lets show the pan box
      this.mPanBox.style.width = width + 'px';
      this.mPanBox.style.height = height + 'px';
      if( ( panX != null ) && ( panX > 0 ) && 
          ( panY != null ) && ( panY > 0 )  )
      {
        var containerOffset = Position.cumulativeOffset( this.mPanel );
        panX += containerOffset[0];
        panY += containerOffset[1];
        
        this.mPanBox.style.left = panX + 'px';
        this.mPanBox.style.top = panY + 'px';
        
        // only show the box if we have a pan
        if( this.mPanel.visible() )
          this.mPanBox.show();
      }     
    }   
  };
  
  this.setImagePanel = function( imagePanel )
  {
    this.mImagePanel = imagePanel;
    this.update();
  };
  
  this.resize = function()
  {
    var width = this.DEFAULT_SIZE[0];
    var height = this.DEFAULT_SIZE[1];
    
    // bring it back
    if( this.mBody.src )
    {
      this.mBody.show();
      
      if( this.mBody.width > 0 )
        width = this.mBody.width;
        
      if( this.mBody.height > 0 )
        height = this.mBody.height;
    }
    
    // can only continue if we have values
    if( width && height )
    {
      this.mPanel.style.width = ( width + ( this.MARGIN * 2 ) ) + 'px';
      this.mPanel.style.height = ( height + ( this.MARGIN * 2 ) ) + 'px';
    }
    
    return true;
  };
  
  this.moveToDefaultPosition = function()
  {
    var screenSize = jshGetWindowSize();
    var position = [];
    position[0] = ( screenSize[0] - this.DEFAULT_SIZE[0] - 40 );
    position[1] = ( screenSize[1] - this.DEFAULT_SIZE[1] - 10 );
    this.moveTo( position[0], position[1] );
  };
  
  this.moveTo = function( x, y ) 
  {
    var offset = Position.cumulativeOffset( this.mContainer );
    var screenSize = jshGetWindowSize();
  
    // keep within limits
    x = Math.max( x, offset[0] );  
    if( ( x + this.mPanel.getWidth() ) > ( screenSize[0] ) )
    {
      x = (  screenSize[0] ) - this.mPanel.getWidth();
    }
  
    y = Math.max( y, offset[1] );
    if( ( y + this.mPanel.getHeight() ) > ( screenSize[1] ) )
    {
      y = ( screenSize[1] ) - this.mPanel.getHeight();
    }
    
    this.mPanel.style.left = x + 'px';
    this.mPanel.style.top = y + 'px';
    
    this.updatePanBox();
    
    return true;
  };
  
  this.getDimensions = function()
  {
    var toReturn = new Array();
    var borderWidth = parseInt( this.mPanel.getStyle( 'borderLeftWidth' ) ) + parseInt( this.mPanel.getStyle( 'borderRightWidth' ) );
    var borderHeight = parseInt( this.mPanel.getStyle( 'borderBottomWidth' ) ) + parseInt( this.mPanel.getStyle( 'borderTopWidth' ) );
    toReturn[ 0 ] = this.mPanel.getWidth() - borderWidth;
    toReturn[ 1 ] = this.mPanel.getHeight() - borderHeight;
    
    return toReturn;
  };
  
  this.hide = function()
  {
    this.mIsHidden = true;
    this.mPanBox.hide();
    
    if( this.mAnimate == true )
    {
      var tp = this;
      var postFunction = function(){ tp.mPanel.hide(); };
      ElementEffects.fadeElement( this.mPanel, 0, 55, .25, postFunction );
    }
    else
    {
      this.mPanel.hide();
    }
  };
  
  this.show = function()
  {
    this.mIsHidden = false;
    this.mPanel.show();
    this.updatePanBox( true );
    
    if( this.mAnimate == true )
    {
      ElementEffects.fadeElement( this.mPanel, 1, 55, .25, null );
    }
  };
  
  this.toggle = function()
  {
    if( this.mIsHidden == true )
    {
      this.show();
    }
    else
    {
      this.hide();
    }
  };
  
  this.isHidden = function()
  {
    return this.mIsHidden;
  };
  
  this.equalsCurrentAction = function( anAction )
  {
    if( anAction )
    {
      if( this.mCurrentAction == anAction )
      {
        return true;
      }
      else if( ( ! this.mCurrentAction ) && ( anAction == this.ACTION_DEFAULT ) )
      {
        return true;
      }
    }
          
    return false;
  };
  
  this.setCurrentAction = function( newAction )
  {
    if( this.mActionInProgress != true )
    {
      if( ! newAction )
        newAction = this.ACTION_DEFAULT;
        
      this.mCurrentAction = newAction;
    }
  };
  
  this.setAnimate = function( animate )
  {
    this.mAnimate = animate;
  };
  
} 


/**
 * Marks the end of a panel move operation
 */
function Static_ThumbnailPanner_EndMove( e, cancelAction )
{
  var sourceElement = jshGetSourceElement( e );
  if( sourceElement.thumbnailPanner )
  {
    var thumbnailPanner = sourceElement.thumbnailPanner;
    
    if( thumbnailPanner.mActionInProgress == true )
    {      
      // reset variables
      thumbnailPanner.mActionInProgress = null;
      
      // reset events
      thumbnailPanner.mGlassPlate.hide();
      thumbnailPanner.mGlassPlate.onmouseup = null;
      thumbnailPanner.mGlassPlate.onmousemove = null;
      thumbnailPanner.mGlassPlate.onmousedown = null;
      thumbnailPanner.mGlassPlate.onmouseout = null;
      
      thumbnailPanner.mContainer.thumbnailPanner = null;      
      thumbnailPanner.mContainer.onmousemove = null;
      thumbnailPanner.mContainer.onmouseup = null;
      
      // reset poistion to original
      if( cancelAction == true )
      {
       // do something? 
      }
      else
      {
        // just endf or now...later we might need to do some post op stuff
        
      }
      
      // clear current action
      thumbnailPanner.setCurrentAction( null );
      
      // reset the last of the variables       
      thumbnailPanner.mMoveStartingX = null;
      thumbnailPanner.mMoveStartingY = null;
      thumbnailPanner.mResizeStartingWidth = null;
      thumbnailPanner.mResizeStartingHeight = null;    
      thumbnailPanner.mOriginalMoveStartingX = null;
      thumbnailPanner.mOriginalMoveStartingY = null;
      thumbnailPanner.mOriginalPanStartingX = null;
      thumbnailPanner.mOriginalPanStartingY = null;
      thumbnailPanner.mOriginalStartingX = null;
      thumbnailPanner.mOriginalStartingY = null;
      thumbnailPanner.mResizeStartingWidth = null;
      thumbnailPanner.mResizeStartingHeight = null;
      thumbnailPanner.mMoveStartingX = null;
      thumbnailPanner.mMoveStartingY = null;
    }
  }
}

/**
 * Marks the state of a panel move operation
 */
function Static_ThumbnailPanner_StartMove( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );  
  if( sourceElement.thumbnailPanner )
  {    
    var thumbnailPanner = sourceElement.thumbnailPanner;
    
    if( thumbnailPanner.equalsCurrentAction( thumbnailPanner.ACTION_MOVE ) || 
        thumbnailPanner.equalsCurrentAction( thumbnailPanner.ACTION_PAN  ) )
    {
      if( !( thumbnailPanner.mActionInProgress == true ) )
      { 
        thumbnailPanner.mActionInProgress = true;
        
        // back up some values incase we cancel or need a reference
        var offset = Position.page( thumbnailPanner.mPanel );        
        thumbnailPanner.mOriginalMoveStartingX = offset[0];
        thumbnailPanner.mOriginalMoveStartingY = offset[1];
        
        // this guy gets updated
        thumbnailPanner.mMoveStartingX = Event.pointerX( e );
        thumbnailPanner.mMoveStartingY = Event.pointerY( e );
        
        // this guy stays the same 
        thumbnailPanner.mOriginalStartingX = Event.pointerX( e );
        thumbnailPanner.mOriginalStartingY = Event.pointerY( e );
        
        // set events on other elements to get a "smooth" motion
        thumbnailPanner.mGlassPlate.show();
        thumbnailPanner.mGlassPlate.thumbnailPanner = thumbnailPanner;      
        thumbnailPanner.mGlassPlate.onmousemove = Static_ThumbnailPanner_Move;
        thumbnailPanner.mGlassPlate.onmouseup = Static_ThumbnailPanner_EndMove;
        thumbnailPanner.mGlassPlate.onmouseout = Static_ThumbnailPanner_EndMove;
        
        thumbnailPanner.mContainer.thumbnailPanner = thumbnailPanner;      
        thumbnailPanner.mContainer.onmousemove = Static_ThumbnailPanner_Move;
        thumbnailPanner.mContainer.onmouseup = Static_ThumbnailPanner_EndMove;
      }
    }
  }
}

/**
 * The actual work of a Move operation which can be either a 
 * Panel move or pan based on what the control is set to
 */
function Static_ThumbnailPanner_Move( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );  
  if( sourceElement.thumbnailPanner )
  {
    // move the panel if we are in move mode
    var thumbnailPanner = sourceElement.thumbnailPanner;
    if( thumbnailPanner.mActionInProgress == true )
    { 
      // current mouse position      
      var endingX = Event.pointerX( e );
      var endingY = Event.pointerY( e );
      
      // cal how many px we are moving
      var difference = $( [ ( endingX - thumbnailPanner.mMoveStartingX ), ( endingY - thumbnailPanner.mMoveStartingY ) ] );
      
      // update values for next time
      thumbnailPanner.mMoveStartingX = endingX;
      thumbnailPanner.mMoveStartingY = endingY;
      
      // do the action
      if( thumbnailPanner.equalsCurrentAction( thumbnailPanner.ACTION_MOVE ) )
      { 
        // calc actual new move position
        var offset = Position.cumulativeOffset( thumbnailPanner.mPanel );      
        var x = offset[0] + difference[0];
        var y = offset[1] + difference[1];
        
        thumbnailPanner.moveTo( x, y );
      }   
      else if( thumbnailPanner.equalsCurrentAction( thumbnailPanner.ACTION_PAN ) )
      { 
        var size = thumbnailPanner.mImagePanel.getCurrentImageSize();
        var ratio = [ ( size[0] / thumbnailPanner.mBody.width ), ( size[1] / thumbnailPanner.mBody.height ) ];
        
        difference[0] = Math.round( difference[0] * ratio[0] );
        difference[1] = Math.round( difference[1] * ratio[1] );
        
        var viewpoint = thumbnailPanner.mImagePanel.getCurrentViewPoint();
        thumbnailPanner.mImagePanel.panTo( ( difference[0] + viewpoint[0] ), ( difference[1] + viewpoint[1] ) );
      }
    }    
  }
}
























