/**
 * Manages fly sliders
 */
FlySliderManager = function(config) {
  // configurable {
  this.selector = ''; // required selector of trigger elements of fly sliders
  this.triggerSelector = ''; // required trigger selector relative to the selector
  this.pictureSelector = '.data .pict'; // required picture selector relative to the selector
  this.pictConfig = {
    size: {
      width: 110,
      height: 110
    }
  }
  // }
  $.extend(this, config);  
}

FlySliderManager.prototype = {
  start: function() {
    this.getElements().each($.proxy(function(i, el) {
      this._initSlider($(el));
    }, this));
  },
  
  _initSlider: function($el) {
    var pictures = this._extractPictures($el);
    if(pictures.length == 0)
      return;
    
    var conf = $.extend({}, this.pictConfig, {
      triggerSelector: $(this.triggerSelector, $el).getIdSelector(),
      pictures: pictures
    })
    new FlySlider(conf).init();
  },
  
  _extractPictures: function($el) {
    var pictures = [];
    $(this.pictureSelector, $el).each(function() {
      pictures.push($.trim($(this).html()));
    });
    return pictures;
  },
  
  getElements: function() {
    return $(this.selector);
  }
}


FlySlider = function(config) {
  // configurable {
  this.triggerSelector = ''; // required selector of a trigger element
  this.pictures = []; // pictures of the slider
  this.pictScrollSpeed = 2000;
  this.size = {
    width: 110,
    height: 110
  }
  // }
  $.extend(this, config);  
  
  this.selector = null;
  this.rendered = false;
  this.animating = false;
}

FlySlider.prototype = {
  init: function() {
    this.initEvents();
  },
  
  initEvents: function() {
    this.getTriggerEl().mousemove($.proxy(this.onMouseMove, this))
                       .mouseout($.proxy(this.onMouseOut, this));
  },

  showAt: function(x, y) {
    this.getEl().show().offset({
      left: x,
      top: y
    });
  },
  
  hide: function() {
    if(this.rendered)
      this.getEl().hide();
  },
  
  startAnimation: function() {
    if(this.animating)
      return;
    
    var start = this.getContainer().position().left;
    if(-start >= this.getContainerWidth() - this.size.width) {
      start = 0;
      this.getContainer().css('left', 0);
    }
//    console.log('start: ' + start);
    var fullTime = this.pictures.length * this.pictScrollSpeed;
    var restTime = Math.round(fullTime + start / this.size.width * this.pictScrollSpeed);
//    console.log('time: ' + restTime);
    this.getContainer().animate({
      left: -(this.getContainerWidth() - this.size.width)
    }, restTime, 'linear', $.proxy(this._restartAnimation, this));
    this.animating = true;
  },
  
  _restartAnimation: function() {
    this.stopAnimation();
    this.startAnimation.defer(1, this);
  },
  
  stopAnimation: function() {
    this.getContainer().stop();
    this.animating = false;
  },
  
  _createMarkup: function() {
    var picts = [];
    for(var i = 0; i < this.pictures.length; i ++)
      picts.push('<td><div class="pict" style="background-image: url(' + this.pictures[i] + ')"></div></td>');
      
    picts.push('<td><div class="pict" style="background-image: url(' + this.pictures[0] + ')"></div></td>');
    
    return $('<div class="fly_slider"><div class="container"><table cellspacing="0"><tr>' + picts.join('') + '</tr></table></div></div>')
           .width(this.size.width)
           .height(this.size.height);
  },
  
  getContainerWidth: function() {
    return this.size.width * (this.pictures.length + 1);
  },
  
  getContainer: function() {
    return $('.container', this.getEl());
  },
  
  getTriggerEl: function() {
    return $(this.triggerSelector);
  },
  
  getEl: function() {
    if(!this.selector) {
      this.selector = this._createMarkup().appendTo($('body')).getIdSelector();
      this.rendered = true;
      this.getContainer().height(this.size.height).width(this.getContainerWidth());
    }
    return $(this.selector);
  },
  
  onMouseMove: function(e) {
    this.showAt(e.pageX + 5, e.pageY - this.size.height - 5);
    this.startAnimation();
  },
  
  onMouseOut: function() {
    this.stopAnimation();
    this.hide();
  }
}
