if(!kronos)
  var kronos = {}

YUI.add('scroller', function(Y) {

var Scroller = function(config) {
  this.name        = config.name;
  this.id          = config.id;
  this.controller  = config.controller;
  this.group       = config.group;
  this.scrollLeft  = false;
  this.scrollRight = false;

  var that = this;
  var nodeId       = '#' + this.id;
  this.element     = Y.one(nodeId);
  
  this.createArrows();
}

Scroller.prototype.createArrows = function() {
  var that = this;
  this.leftArrow = this._createArrow('left');
  this.rightArrow = this._createArrow('right');
  
  // And hook mouse over and out to re-display the arrows
  var node = Y.one('#scroller-' + this.name);
  var parentNode = node.get('parentNode');
  var handleMouseOver = function(evt) {
    that.handleMouseOver(evt);
  }
  var handleMouseOut = function(evt) {
    that.handleMouseOut(evt);
  }
  var handleClick = function(evt) {
    that.handleClick(evt);
  }
  
  Y.on('click', handleClick, node);
  Y.on('mouseover', handleMouseOver, parentNode);
  Y.on('mouseout', handleMouseOut, parentNode);
}

//-----------------------------------------------------------------------------------------------------------
//                                              EVENT HANDLERS
//===========================================================================================================

Scroller.prototype.handleClick = function(evt) {
  var group = this.group;
  if(group.state == kronos.GROUP_SHRUNK || group.state == kronos.GROUP_SHRINKING)
    this.controller.expand(group);
  else
    this.controller.shrink(group, true);
}

Scroller.prototype.handleMouseOver = function() {
  var group = this.group;
  if(group.state == kronos.GROUP_EXPANDED) {
    if(this.shouldDisplayArrows())
      this.displayArrows(true);
  }
  
  if(this.mouseOverListener) {
    var evt = { group : this.group };
    this.mouseOverListener(evt);
  }
}

Scroller.prototype.handleMouseOut = function() {
  this.displayArrows(false);
  
  if(this.mouseOutListener) {
    var evt = { group : this.group };
    this.mouseOutListener(evt);
  }
}

//
// Arrows manipulation
//

Scroller.prototype.shouldDisplayArrows = function() {
  var node = Y.one('#scroller-' + this.name);
  var parentNode = node.get('parentNode');
  
  var w = this.getScrollableWidth();
  var parentW = parentNode.get('offsetWidth');
  if(w > parentW)
    return true;
  else
    return false;
}

Scroller.prototype._createArrow = function(dir) {
  var that = this;
  var contentNode = Y.one('#' + this.id).get('parentNode');
  if(dir == 'left')
    var imgName = 'arrow-l.png';
  else
    var imgName = 'arrow-r.png';
  contentNode.append('<img src="images/' + imgName + '" width="44" height="340" style="visibility: hidden; position: absolute; opacity: 0.6; top: 0" class="' + dir + '-arrow" />');
  var arrow = contentNode.one('.' + dir + '-arrow');
  if(dir == 'left') {
    arrow.on('mousedown', function(e) { that.startScrolling('left'); }, arrow);
    arrow.setStyle('left', '0px');
  }
  else{
    arrow.on('mousedown', function(e) { that.startScrolling('right'); }, arrow);
    arrow.setStyle('right', '0px');
  }
  arrow.on('mouseup', function(e) { that.stopScrolling(e); })
  return arrow;
}

Scroller.prototype.displayArrows = function(show) {
  var showStyle = show ? 'visible' : 'hidden';
  this.leftArrow.setStyle('visibility', showStyle);
  this.rightArrow.setStyle('visibility', showStyle);
}

/**
 * Starts moving the content. It will be stopped either manually or by reaching left or right edge.
 */
Scroller.prototype.startScrolling = function(direction) {
  var that = this;
  var node = Y.one('#' + this.id);
  var left = node.get('offsetLeft');
  var newLeft = this.calculateNewLeft(direction);
  
  if(this._scrollAnim) {
    this._scrollAnim.stop();
    this._scrollAnim = null;
  }
  
  if(left != newLeft) {
    var scrollingEnd = function(evt) {
      if(that._scrollAnim) {
        var newLeft2 = that.calculateNewLeft(direction);
        if(newLeft != newLeft2) {
          that._scrollAnim.set('to', { left : newLeft2 });
          that._scrollAnim.run();
        }
      }
    }

    var anim = new Y.Anim({
      node : node,
      to : { left : newLeft },
      end : scrollingEnd
    });
    this._scrollAnim = anim;
    this._scrollAnim.run();
  }
}

/**
 * Calculates new left position of the scrollable area.
 */
Scroller.prototype.calculateNewLeft = function(direction) {
  var node = Y.one('#' + this.id);
  var rightEdge = this.getScrollableWidth();
  // Get width of the parent
  var parent = node.get('parentNode');
  var parentWidth = parent.get('offsetWidth');
  
  // Compute new left
  var left = node.get('offsetLeft');
  var newLeft = left;
  if(direction == 'left')
    newLeft += 450;
  else
    newLeft -= 450;
  // Now correct the value of new left
  if(newLeft > 0)
    newLeft = 0;
  if(newLeft + rightEdge < parentWidth)
    newLeft = parentWidth - rightEdge;
  return newLeft;
}

Scroller.prototype.stopScrolling = function() {
  if(this._scrollAnim)
    this._scrollAnim = null;
}

Scroller.prototype.setupAnimation = function(cfg) {
  var that = this;
  if(this._anim) {
    this._anim.stop();
    this._anim = null;
  }

  var node = Y.one('#' + this.id);  
  cfg.to.left = function() {
    return node.get('offsetLeft');
  }

  var resizeAnim = new Y.Anim({
    duration : kronos.ROW_EXPANSION_TIME,
    node : node,
    from : cfg.from, to : cfg.to
  });
  var scrollAnim = new Y.Anim({
    duration : kronos.ROW_EXPANSION_TIME,
    node : node,
    to : {
      left : 0
    }
  });
  this._anim = resizeAnim;
}

Scroller.prototype.stopAnimation = function() {
  
}

Scroller.prototype.animate = function(forward) {
  var that = this;
  
  if(forward) {
    this._anim.set('reverse', false);
    this._anim.run();
  }
  else {
    this._anim.set('reverse', true);
    this._anim.run();
  }
}

Scroller.prototype.getScrollableWidth = function() {
  var group = this.group;
  var node = Y.one('#' + this.name);
  // Get the width = right edge of the last image that is actually visible
  var width = 0;
  for(var itemName in group.items) {
    var item = group.items[itemName];
    if(item.visible) {
      var itemRight = item.left + item.width;
      width = Math.max(width, itemRight);
    }
  }
  
  return width;
}

kronos.Scroller = Scroller;

}, '1.0.0' /* module version */, {
  requires: ['base', 'node', 'anim']
});

