text: var Node   = require('../document/Node');
  var Metric = require('../../component/Metric');
  var CSS    = require('../document/CSS');
  var DocumentEvent = require('../document/DocumentEvent'),
      NodeEvent     = require('../document/NodeEvent');
  var Mouse  = require('../document/Mouse');
  
  function ScrollBar(parentNode,targetNode,wrapHeight) {
      this._parentNode = parentNode;
      this._targetNode = targetNode;
      this._wrapHeight = wrapHeight;
  
      var wrap   = this._wrapNode   = new Node().setStyleClass(CSS.ScrollWrap),
          node   = this._node       = new Node().setStyleClass(CSS.ScrollBar),
          track  = this._trackNode  = new Node().setStyleClass(CSS.ScrollBarTrack),
          thumb  = this._thumbNode  = new Node().setStyleClass(CSS.ScrollBarThumb);
  
      parentNode.removeChild(targetNode);
      parentNode.addChild(wrap);
      parentNode.addChildAt(node,0);
  
      wrap.addChild(targetNode);
      node.addChild(track);
      track.addChild(thumb);
  
      this._mouseThumbOffset = 0;
      this._scrollHeight = 0;
      this._scrollUnit   = 0;
      this._scrollMin    = 0;
      this._scrollMax    = 0;
  
      thumb.setPositionY(Metric.SCROLLBAR_TRACK_PADDING);
      thumb.addEventListener(DocumentEvent.MOUSE_DOWN,this._onThumbDragStart.bind(this));
  
      this._isValid  = false;
      this._enabled = false;
  
      var nodeElement = node.getElement(),
          thumbElement = thumb.getElement();
      var self = this;
      this._onMouseWheel = function(e){
          var sender = e.sender,
              hoverElement = sender.getHoverElement();
          if(hoverElement != nodeElement && hoverElement != thumbElement){
              return;
          }
          var scrollStep = self._scrollHeight * 0.0125;
          self._scroll(thumb.getPositionY() + sender.getWheelDirection() * scrollStep * -1);
          e.data.preventDefault();
      };
  
      this.addMouseListener();
  }
  
  ScrollBar.prototype.update = function(){
      var target = this._targetNode,
          thumb = this._thumbNode;
  
      var padding = Metric.SCROLLBAR_TRACK_PADDING;
  
      var targetWrapHeight = this._wrapHeight,
          targetHeight = target.getHeight(),
          trackHeight = targetWrapHeight - padding * 2;
  
      thumb.setHeight(trackHeight);
  
      var ratio = targetWrapHeight / targetHeight;
  
      this._isValid = false;
  
      if (ratio > 1.0){
          return;
      }
      var thumbHeight = trackHeight * ratio;
  
      this._scrollHeight = trackHeight;
      this._scrollUnit   = targetHeight - this._scrollHeight - padding * 2;
      this._scrollMin    = padding;
      this._scrollMax    = padding + trackHeight - thumbHeight;
  
      thumb.setHeight(thumbHeight);
  
      this._isValid = true;
  };
  
  ScrollBar.prototype._scroll = function(y){
      var min  = this._scrollMin,
          max  = this._scrollMax,
          pos  = Math.max(min, Math.min(y,max)),
          pos_ = (pos-min)/(max-min);
  
      this._thumbNode.setPositionY(pos);
      this._targetNode.setPositionY(pos_ * this._scrollUnit * -1);
  };
  
  
  ScrollBar.prototype._onThumbDragStart = function () {
      if (!this._isValid || this._enabled){
          return;
      }
      var eventMove = DocumentEvent.MOUSE_MOVE,
          eventUp = DocumentEvent.MOUSE_UP;
  
      var mouse = Mouse.get();
      var trackOffset = this._trackNode.getPositionGlobalY();
  
      this._mouseThumbOffset = mouse.getY() - this._thumbNode.getPositionGlobalY();
  
      var self = this;
      var onDrag = function () {
              self._scroll(mouse.getY() - trackOffset - self._mouseThumbOffset);
          },
          onDragEnd = function () {
              document.removeEventListener(eventMove, onDrag, false);
              document.removeEventListener(eventUp, onDragEnd, false);
          };
  
      document.addEventListener(eventMove, onDrag, false);
      document.addEventListener(eventUp, onDragEnd, false);
      this._scroll(mouse.getY() - trackOffset - self._mouseThumbOffset);
  };
  
  
  ScrollBar.prototype.enable = function () {
      this._enabled = false;
      this._updateAppearance();
  };
  
  ScrollBar.prototype.disable = function () {
      this._enabled = true;
      this._updateAppearance();
  };
  ScrollBar.prototype.reset = function () {
      this._scroll(0);
  };
  
  ScrollBar.prototype._updateAppearance = function () {
      if (this._enabled) {
          this._node.setStyleProperty('display', 'none');
          this._targetNode.setPositionY(0);
          this._thumbNode.setPositionY(Metric.SCROLLBAR_TRACK_PADDING);
      } else {
          this._node.setStyleProperty('display', 'block');
      }
  };
  
  ScrollBar.prototype.isValid = function () {
      return this._isValid;
  };
  
  ScrollBar.prototype.setWrapHeight = function (height) {
      this._wrapHeight = height;
      this.update();
  };
  
  ScrollBar.prototype.removeTargetNode = function () {
      return this._wrapNode.removeChild(this._targetNode);
  };
  
  ScrollBar.prototype.removeMouseListener = function(){
      Mouse.get().removeEventListener(DocumentEvent.MOUSE_WHEEL,this,'_onMouseWheel');
  };
  
  ScrollBar.prototype.addMouseListener = function(){
      Mouse.get().addEventListener(DocumentEvent.MOUSE_WHEEL,this,'_onMouseWheel');
  };
  
  ScrollBar.prototype.removeFromParent = function () {
      var parentNode = this._parentNode,
          rootNode = this._node,
          targetNode = this._targetNode;
  
      rootNode.removeChild(targetNode);
      parentNode.removeChild(this._wrapNode);
      parentNode.removeChild(rootNode);
  
      return targetNode;
  };
  
  ScrollBar.prototype.getWrapNode = function () {
      return this._wrapNode;
  };
  
  ScrollBar.prototype.getNode = function () {
      return this._node;
  };
  
  ScrollBar.prototype.getTargetNode = function () {
      return this._targetNode;
  };
  
  
  module.exports = ScrollBar;