/* 
 *  NAME
 *    createSlider
 *  SYNOPSIS
 *    var slider = createSlider(cfg) ;
 *   
 *  AUTHOR:           Stergios Marinopoulos, stergios_marinopoulos at yahoo dot com
 *  CREATION DATE:    3/1/2007
 *  HISTORY:
 *  IDEAS:
 *
 *
 *  // Configuration object literal:
 *
 *      var cfg = {
 *        containerDiv:      'sliderContainerDiv',   // Surrounding container.  Both Thumbs must be inside.
 *        leftHandleDiv:     'leftHandleDiv',        // Left thumb.  Set it's back ground to the image you want.
 *        rightHandleDiv:    'rightHandleDiv',       // Right thumb.  Set it's back ground to the image you want.
 *        groupName:         'smSlider',             // A unique name.
 *        minValue:          0,                      // The minimum value for the slider range.
 *        maxValue:          100,                    // The maximum value for the slider range.
 *        callBack:          callBack,               // The call back function for when new values are set.  Values are on the range [minValue, maxValue]
 *        stepCount:         10,                     // The minimum increment required for a thumb move. 
 *        allowEqual:        true,                   // (Default==true) Are the 2 handles allowed to have the same value?
 *                                                   //  Useful for when the two hanles cannot have the same value.  Thanks to 
 *                                                   //  William Paoli for the idea!
 *        leftThumbStart:    10                      // Optional. Starting left value
 *        rightThumbStart:   20                      // Optional. Starting right value
 *        leftMoveCallBack:  mouseMoveCallBackLeft,  // Optional. The call back function for left mouse move events.   Values are on the range [minValue, maxValue]
 *        rightMoveCallBack: mouseMoveCallBackRight, // Optional. The call back function for right mouse move events.  Values are on the range [minValue, maxValue]
 *
 *      };
 *
 *
 *  // Create and initiate a new slider:
 *
 *      var slider = createSlider(cfg) ;
 *      slider.init() ;
 *
 *  //  Reset a slider with new min and max values, and reset the thumb handles.
 *      slider.reset(newMinValue, newMaxValue) ;
 *
 *
 *  // Call Back Examples:
 *
 *      var callBack = function (v1, v2, sliderContainer) {
 *        console.log(v1 + ' -- ' + v2 + ' -- ' + sliderContainer) ;
 *      };
 *
 *      var mouseMoveCallBackLeft = function (v, sliderContainer) {
 *        console.log("Mouse Move Left CB: %o for ", v, sliderContainer) ;
 *      };
 *
 *      var mouseMoveCallBackRight = function (v, sliderContainer) {
 *        console.log("Mouse Move Right CB: %o for ", v, sliderContainer) ;
 *      };
 *
 *  // CSS examples:
 *      
 *      #sliderContainerDiv4
 *      {
 *        position: absolute;
 *        top:200px; left:600px; width:200px; height:20px;
 *        background:url(/img/horizSlider_background.gif) 0 0 repeat-x; 
 *      }
 *      #leftHandleDiv4
 *      {
 *        position: absolute;
 *        top:0px; left:0px; width:18px; height:18px;
 *        background:url(/img/horizSlider.png) 0 0 no-repeat; 
 *        color: #F00; 
 *        border: 0;
 *      }
 *      #rightHandleDiv4
 *      {
 *        position: absolute;
 *        top:0px; right:0px; width:18px; height:18px;
 *        background:url(/img/horizSlider.png) 0 0 no-repeat; 
 *        color: #F00; 
 *        border: 0;
 *      }
 *
 *
*/
var createSlider = function(cfg) {

    var cs ;                  // = cfg ; 
    var leftThumb = null;
    var rightThumb = null;
    var handleDragged = null;
    var bb ;                  // = document.getElementById(cs.containerDiv);
    var leftThumbDiv ;        // = document.getElementById(cs.leftHandleDiv);
    var thumbRegion ;         // = YAHOO.util.Dom.getRegion(leftThumbDiv) ;
    var thumbWidth ;          // = thumbRegion.right - thumbRegion.left ;
    var containerRegion ;     // = YAHOO.util.Dom.getRegion(bb) ;
    var containerWidth ;      // = containerRegion.right - containerRegion.left;
    var containerLeft ;       // = containerRegion.left ;
    var span ;                // = containerWidth - 2*thumbWidth ;
    var tickCount ;           // = 1 ;
    var constraintAdjust = 0;
    var rightThumbDiv;        //= document.getElementById(cs.rightHandleDiv);
    var leftThumbValue;
    var rightThumbValue;

    var resetLeftConstraint = function(ltx, rtx) {
        var leftThumbTravel2Left  = Number(ltx - containerLeft).toFixed(0) ;
        var leftThumbTravel2Right = Number(rtx - ltx - thumbWidth ).toFixed(0) ;
        if ( ! cs.allowEqual ) {
            leftThumbTravel2Right -= constraintAdjust ; 
        }
        leftThumb.setXConstraint(leftThumbTravel2Left, leftThumbTravel2Right, Math.floor(tickCount) );
        leftThumb.resetConstraints(true);  
    };

    var resetRightConstraint = function (ltx, rtx) {
        // (ltx, rts) = X positions of the the handles in page coordinates.
        var rightThumbTravel2Left  = Number(rtx - ltx - thumbWidth).toFixed(0) ;
        var rightThumbTravel2Right = Number((containerLeft + containerWidth) - ( rtx + thumbWidth )).toFixed(0) ;
        if ( ! cs.allowEqual ) {
            rightThumbTravel2Left -= constraintAdjust ; 
        }
        rightThumb.setXConstraint(rightThumbTravel2Left, rightThumbTravel2Right, Math.floor(tickCount) );
        rightThumb.resetConstraints(true);  
    };

    return {
      init: function() {
          YAHOO.util.DragDropMgr.clickPixelThresh = 1 ;
          cs = cfg ; // configSlider
          var configDD = {scroll:false};
          bb = YAHOO.util.Dom.get(cs.containerDiv);

          leftThumbDiv    = YAHOO.util.Dom.get(cs.leftHandleDiv);
          leftThumbValue  = cs.minValue;
          leftThumb       = new YAHOO.util.DD(cs.leftHandleDiv, cs.groupName, configDD);

          rightThumbDiv   = YAHOO.util.Dom.get(cs.rightHandleDiv);
          rightThumbValue = cs.maxValue;
          rightThumb      = new YAHOO.util.DD(cs.rightHandleDiv, cs.groupName, configDD);

          thumbRegion = YAHOO.util.Dom.getRegion(leftThumbDiv) ;
          thumbWidth = thumbRegion.right - thumbRegion.left ;

          containerRegion = YAHOO.util.Dom.getRegion(bb) ;
          containerWidth  = containerRegion.right - containerRegion.left ;
          containerLeft   = containerRegion.left ;
          span            = containerWidth - 2*thumbWidth ;
          tickCount       = 1 ;

          if ( cs['stepCount'] ) {
              if ( cs.stepCount > 1 ) {
                  tickCount = span / cs.stepCount ;
                  tickCount = tickCount.toFixed(0) ;
                  constraintAdjust = tickCount / 2;
                  constraintAdjust = constraintAdjust.toFixed(0) ;
              }
          } 
          if (! cs.hasOwnProperty('allowEqual') ){
              cs['allowEqual'] = true ;
          }
          // left
          var leftTravel2Right = containerWidth - 2 * thumbWidth ;
          if ( ! cs.allowEqual ) {
              leftTravel2Right -= constraintAdjust ; 
          }
          leftThumb.setXConstraint(0, leftTravel2Right, Math.floor(tickCount));
          leftThumb.setYConstraint(0, 0, 0);

          // right
          var rightTravel2Left = containerWidth - 2 * thumbWidth ;
          if ( ! cs.allowEqual ) {
              rightTravel2Left -= constraintAdjust ; 
          }
          rightThumb.setXConstraint(rightTravel2Left, 0, Math.floor(tickCount));
          rightThumb.setYConstraint(0, 0, 0);

          var endDrag = function(e){
              var x     = YAHOO.util.Dom.getX(handleDragged);
              if ( leftThumbDiv === handleDragged) {
                  resetRightConstraint(x, YAHOO.util.Dom.getX(rightThumbDiv));
                  leftThumbValue = mapValue(x + thumbWidth);
                  cs.callBack(leftThumbValue, rightThumbValue, cs.containerDiv, false, bb) ;
              } else if ( rightThumbDiv === handleDragged) {
                  resetLeftConstraint(YAHOO.util.Dom.getX(leftThumbDiv),x);
                  rightThumbValue = mapValue(x);
                  cs.callBack( leftThumbValue, rightThumbValue, cs.containerDiv, false, bb) ;
              }
          };
          rightThumb.endDrag   = endDrag;
          leftThumb.endDrag    = endDrag;

          var startDrag = function(x,y){
          };
          rightThumb.startDrag = startDrag;
          leftThumb.startDrag  = startDrag;

          var mapValue = function(p){
              var base = containerLeft + thumbWidth ;
              var v = (p - base)/span*(cs.maxValue -cs.minValue)+cs.minValue;
              if ( cs['stepCount'] ) {
                  // compute the stepInterval
                  var stepInterval = (cs.maxValue - cs.minValue)/cs.stepCount ;
                  // convert to a zero minimum base
                  var zeroBase = v - cs.minValue ;
                  // divide by stepInterval to get SI Units
                  var stepIntervalUnits =  zeroBase / stepInterval ;
                  // round to the proper number of step intervals
                  var stepIntervalUnitsRounded = Math.round(stepIntervalUnits);
                  // convert back to original range
                  v = stepIntervalUnitsRounded * stepInterval + cs.minValue ;
              } 
              return v ;
          };

          var mouseDown = function(e){
              // doubt this is used
              handleDragged = YAHOO.util.Event.getTarget(e) ;
              var x = YAHOO.util.Dom.getX(handleDragged) ;
              var y = YAHOO.util.Dom.getY(handleDragged) ;
          };
          rightThumb.onMouseDown = mouseDown ;
          leftThumb.onMouseDown  = mouseDown ;

          var mouseMove = function(e){
              var lThumbValue 
                  = mapValue(YAHOO.util.Dom.getX(leftThumbDiv) + thumbWidth);
              var rThumbValue = mapValue(YAHOO.util.Dom.getX(rightThumbDiv));
              if ( handleDragged === leftThumbDiv ) {
                  cs.leftMoveCallBack( lThumbValue, 
                                       rThumbValue,
                                       cs.containerDiv, 
                                       bb
                                     );
              } else if ( handleDragged === rightThumbDiv ) {
                  cs.rightMoveCallBack( lThumbValue, 
                                       rThumbValue,
                                       cs.containerDiv, 
                                       bb
                                     );
              }
          };

	  // set start values if any
          // left
          if (cs.leftThumbStart){
              this.setValue(cs.leftThumbStart, 'left') ;
          }
          // right
          if (cs.rightThumbStart){
              this.setValue(cs.rightThumbStart, 'right') ;
          }
	  // set call backs if any
          // left
          if (cs.leftMoveCallBack){
              leftThumb.onDrag  = mouseMove ;
          }
          // right
          if (cs.rightMoveCallBack){
              rightThumb.onDrag = mouseMove ;
          }
      },

      reset: function(min, max, newStepCount) {
          cs.minValue = min;
          cs.maxValue = max;
          if ( newStepCount > 1 ) {
              tickCount = span / newStepCount ;
              tickCount = tickCount.toFixed(1) ;
              constraintAdjust = tickCount / 2;
              constraintAdjust = constraintAdjust.toFixed(0) ;
          } else {
              tickCount = 1; 
          }
          this.setValue(min, 'left') ;
          this.setValue(max, 'right') ;
      },

      setValue: function(x, whichHandle) {
          if ( whichHandle === 'left' ) {
              if ( x < cs.minValue ) {
                  x = cs.minValue ; 
              }
              var base = containerLeft + thumbWidth ;
              var ltx02 = (x - cs.minValue) * span / (cs.maxValue - cs.minValue)  + base - thumbWidth ;
              var rtx02 = YAHOO.util.Dom.getX(rightThumbDiv) ;
              if ( ltx02 + thumbWidth > rtx02 ) {
                  return ;
              }
              YAHOO.util.Dom.setX(leftThumbDiv, ltx02) ;
              leftThumbValue = x ;
              resetRightConstraint(ltx02, rtx02) ;
              resetLeftConstraint (ltx02, rtx02) ;  // Positions of the handles

          } else if ( whichHandle === 'right' ) {
              if ( x > cs.maxValue ) {
                  x = cs.maxValue ; 
              }
              var base = containerLeft + thumbWidth ;
              var rtx03 = (x - cs.minValue) * span / (cs.maxValue - cs.minValue)  + base ;
              var ltx03 = YAHOO.util.Dom.getX(leftThumbDiv) ;  
              if ( ltx03 + thumbWidth > rtx03 ) {
                  // cannot set the right handle past the left
                  return ;
              }
              YAHOO.util.Dom.setX(rightThumbDiv, rtx03); 
              rightThumbValue = x;
              resetLeftConstraint (ltx03, rtx03);  // Positions of the handles
              resetRightConstraint(ltx03, rtx03);  // Positions of the handles
          }
      }
  };
}; 

