/* 
 *  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!
 *        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]
 *        leftDisplay:       'yearLeftDisplay',      // Optional. Id of element which has the left thumb value displayed in.
 *        rightDisplay:      'yearRightDisplay',     // Optional. Id of element which has the right thumb value displayed in.
 *        formatFunction:    'priceFormatFunction'   // Optional. Function to format slider values before in placing them in the left or right display.
 *
 *      };
 *
 *
 *  // 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 ; // configSlider
  var leftThumb = null, 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) {    
    constratinAdjust = 0;
    var leftThumbTravel2Left  = ltx - containerLeft;
    var leftThumbTravel2Right = rtx - ( ltx + thumbWidth ) +20;
   //QQQQ console.log("\tleftThumbTravel2Left = %d", leftThumbTravel2Left) ;
    //QQQQ console.log("\tleftThumbTravel2Right = %d", leftThumbTravel2Right) ;
    if ( ! cs.allowEqual ) {
      leftThumbTravel2Right -= constraintAdjust ; 
    }
    leftThumb.setXConstraint(leftThumbTravel2Left, leftThumbTravel2Right, Math.floor(tickCount) );
    leftThumb.resetConstraints(true);      

  };

  var resetRightConstraint = function (ltx, rtx) {
    constraintAdjust = 0;
    var rightThumbTravel2Left  = rtx - ltx - thumbWidth -20;
    var rightThumbTravel2Right = (containerWidth + containerLeft) - ( rtx + thumbWidth ) ;
   // QQQQ console.log("\trightThumbTravel2Left = %d", rightThumbTravel2Left) ;
   // QQQQ console.log("\trightThumbTravel2Right = %d", rightThumbTravel2Right) ;
    if ( ! cs.allowEqual ) {
      rightThumbTravel2Left -= constraintAdjust ; 
    }
    rightThumb.setXConstraint(rightThumbTravel2Left, rightThumbTravel2Right, Math.floor(tickCount) );
    rightThumb.resetConstraints(true);  

  };

  return {
    
    // Why wouldn't you allow access to these resetting functions?
    resetRight: resetRightConstraint,
    resetLeft: resetLeftConstraint,

    init: function() {

      YAHOO.util.DragDropMgr.clickPixelThresh = 1 ;
     
      cs = cfg ; // configSlider


 rightThumbValue = FilterPage.Results.dateFilter[1];
 leftThumbValue = FilterPage.Results.dateFilter[0];

 
      var configDD = {scroll:false};

      bb = document.getElementById(cs.containerDiv);
      bb.mm_cfg = cfg ;
      leftThumbDiv = document.getElementById(cs.leftHandleDiv);
      leftThumb = new YAHOO.util.DD(cs.leftHandleDiv, 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 ;

      //console.log("containerWidth = %d", containerWidth) ;
      //console.log("containerLeft = %d", containerLeft) ;
      // QQQQ console.log("thumbWidth = %d", thumbWidth) ;
      // QQQQ console.log("containerRegion = %o", containerRegion ) ;
      
      

      span = containerWidth - 2*thumbWidth ;
      // QQQQ console.log("span = %d", span) ;
      tickCount = 1 ;

      if ( cs['leftDisplay'] ) {
        bb.mm_cfg.leftDisplayElem = document.getElementById(cs.leftDisplay);
        if ( cs['formatFunction'] ) {
          bb.mm_cfg.leftDisplayElem.innerHTML = cs.formatFunction(cs.minValue) ;
        } else {
          bb.mm_cfg.leftDisplayElem.innerHTML = cs.minValue ;
        }

      }
      if ( cs['rightDisplay'] ) {
        bb.mm_cfg.rightDisplayElem = document.getElementById(cs.rightDisplay);
        if ( cs['formatFunction'] ) {
          bb.mm_cfg.rightDisplayElem.innerHTML = cs.formatFunction(cs.maxValue) ;
        } else {
          bb.mm_cfg.rightDisplayElem.innerHTML = cs.maxValue ;
        }
      }

      if ( cs['stepCount'] ) {
        if ( cs.stepCount > 1 ) {
          tickCount = containerWidth / cs.stepCount ;
          // QQQQ console.log("tickCount: %o:", tickCount) ;

          tickCount = tickCount.toFixed(0) ;
          // QQQQ console.log("tickCount (after toFixed(1)): %o:", tickCount) ;
          constraintAdjust = tickCount / 2;
          constraintAdjust = constraintAdjust.toFixed(0) ;
        }
      } 
      if (! cs.hasOwnProperty('allowEqual') ){
        cs['allowEqual'] = true ;
      }
      
      // resetting constraint adjust
      constraintAdjust = 0;
      var leftTravel2Right = containerWidth - 2 * thumbWidth ;
      // QQQQ console.log("leftTravel2Right = %d", leftTravel2Right) ;
      if ( ! cs.allowEqual ) {
        leftTravel2Right -= constraintAdjust ; 
      }
      //console.log("leftTravel2Right: " + leftTravel2Right + " tickCount: " + Math.floor(tickCount))
      
      leftThumb.setXConstraint(0, leftTravel2Right, Math.floor(tickCount));
      leftThumb.setYConstraint(0, 0, 0);

      rightThumbDiv = document.getElementById(cs.rightHandleDiv);
      var rightTravel2Left = containerWidth - 2 * thumbWidth ;
      // QQQQ console.log("rightTravel2Left = %d", rightTravel2Left) ;

      rightThumb = new YAHOO.util.DD(cs.rightHandleDiv, cs.groupName, configDD);
      if ( ! cs.allowEqual ) {
        rightTravel2Left -= constraintAdjust ; 
      }
      rightThumb.setXConstraint(rightTravel2Left, 0, Math.floor(tickCount));
      rightThumb.setYConstraint(0, 0, 0);
            
      var mapValue = function(p)
      {
        var base = containerLeft + thumbWidth ;
        var v = (p - base)/span * (cs.maxValue - cs.minValue);

        if ( cs['stepCount'] ) {
          // compute the stepInterval
          var stepInterval = (cs.maxValue - cs.minValue) / (cs.stepCount - 1) ;
          // 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 ;
        } 
        
        // new method.
        var v = (p/containerWidth)*cs.stepCount;
        v = Math.round(v);

        return v ;
      };
      
      var endDrag = function(e)
      {
        // QQQQ console.log("endDrag: event: %o", e);
        // Once again, YUI fails. getX actually ends up doubling the thumbWidth; so subtract it out (twice) and add half to get
        // center of our slider

var x = YAHOO.util.Dom.getX(handleDragged) - 1.5*thumbWidth ;
        

     //   if (typeof isIE7 != 'undefined' && leftThumbDiv === handleDragged) x = x - thumbWidth;
        
        var y = YAHOO.util.Dom.getY(handleDragged) ;
        // QQQQ console.log("\t(x,y) (%d,%d)", x,y) ;

        if ( leftThumbDiv === handleDragged) {

          // QQQQ console.log("Reseting rightThumb constraints");
          var rtx01 = YAHOO.util.Dom.getX(rightThumbDiv) ;

          resetRightConstraint(x, rtx01) ;
       
          leftThumbValue = mapValue(x) + cs.minValue;
          cs.callBack( leftThumbValue, rightThumbValue, cs.containerDiv, false, bb) ;
	//	 console.log(FilterPage.Results.dateFilter[0] + " left") ;

	//	 console.log(FilterPage.Results.dateFilter[1] + " right") ;

        } else if ( rightThumbDiv === handleDragged) {
		
          // QQQQ console.log("Reseting leftThumb constraints");
          var ltx01 = YAHOO.util.Dom.getX(leftThumbDiv) ;

          resetLeftConstraint(ltx01, x) ;

          rightThumbValue = mapValue(x) ;
          cs.callBack( leftThumbValue, rightThumbValue, cs.containerDiv, false, bb) ;
		 //console.log(FilterPage.Results.dateFilter[0] + " left") ;

		 //console.log(FilterPage.Results.dateFilter[1] + " right") ;
				//alert();
			
        }
        //handleDragged.style.background = "url(img/horizSlider.png)" ;

      } ;
      rightThumb.endDrag   = endDrag ;
      leftThumb.endDrag    = endDrag ;

      var startDrag = function(x,y)
      {
        //handleDragged.style.background = "url(img/horizSlider_on.png)" ;
      } ;

      rightThumb.startDrag = startDrag ;
      leftThumb.startDrag  = startDrag ;

      var mouseDown = function(e)
      {
        // QQQQ console.log("mouseDown: event: %o", e);
        handleDragged = YAHOO.util.Event.getTarget(e) ;
        // QQQQ console.log("\telem: %o", handleDragged) ;
        var x = YAHOO.util.Dom.getX(handleDragged) ;

        var y = YAHOO.util.Dom.getY(handleDragged) ;
        // QQQQ console.log("\t(x,y) (%d,%d)", x,y) ;

      } ;

      rightThumb.onMouseDown = mouseDown ;
      leftThumb.onMouseDown  = mouseDown ;

      var mouseMove = function(e) 
      {
        var x_mm ;
        // QQQQ var xMapped ;

        if ( handleDragged === leftThumbDiv ) {

          x_mm = YAHOO.util.Dom.getX(leftThumbDiv) ;

          var tmpLeftThumbValue = mapValue(x_mm + thumbWidth);
          // QQQQ xMapped = tmpLeftThumbValue ;
          cs.leftMoveCallBack( tmpLeftThumbValue, cs.containerDiv, bb ) ;

        } else if ( handleDragged === rightThumbDiv ) {

          x_mm = YAHOO.util.Dom.getX(rightThumbDiv) ;
          var tmpRightThumbValue = mapValue(x_mm) ;
          // QQQQ xMapped = tmpRightThumbValue ;
          cs.rightMoveCallBack( tmpRightThumbValue, cs.containerDiv, bb ) ;

        }
        // QQQQ console.log("mouseMove: event: %o\n\telem: %o\n\t(x: %o)", e, h, x_mm);
        // QQQQ console.log("mouseMove: (xMapped: %o)", xMapped);

      } ;

      if ( cs['leftMoveCallBack'] ) {
        leftThumb.onDrag  = mouseMove ;
      }
      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) {
      // QQQQ console.log("slider.setValue x: %o, handle: %o", 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) ;
        // QQQQ console.log("ltx: %o, rtx: %o, delta: %o", ltx02, rtx02, rtx02 - ltx02) ;
        if ( ltx02 + thumbWidth > rtx02 ) {
          // cannot set the left handle before the right
          // QQQQ console.log("skipping...") ;
          return ;
        }
        YAHOO.util.Dom.setX(leftThumbDiv, ltx02) ;
        leftThumbValue = x ;
        resetRightConstraint(ltx02, rtx02) ;

        if ( cs['leftDisplay'] ) {
          bb.mm_cfg.leftDisplayElem.innerHTML = x ;
        }

      } 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) ;
        // QQQQ console.log("ltx: %o, rtx: %o, delta: %o", ltx03, rtx03, rtx03 - ltx03) ;
        if ( ltx03 + thumbWidth > rtx03 ) {
          // cannot set the right handle past the left
          // QQQQ console.log("skipping...") ;
          return ;
        }
        YAHOO.util.Dom.setX(rightThumbDiv, rtx03) ;
        rightThumbValue = x ;
        resetLeftConstraint(ltx03, rtx03) ;

        if ( cs['rightDisplay'] ) {
          bb.mm_cfg.rightDisplayElem.innerHTML = x ;
        }

      }

    },

    getValues: function() {
      return [leftThumbValue, rightThumbValue] ;
    },


    getRange: function() {
      return [cs.minValue, cs.maxValue] ;
    }


  };
};