Shifter = {
  config: {
    changeAnimationTime: 1000,
    autoTimeoutDelay: 5000,
    list: [
      {
        img: 'http://server/image.jpg',
        url: 'http://server/link/'
      },
    ],
    bannerSize: { w: 1920, h: 1080 },
    buttonSize: { w: 20, h: 20 }
  },
  lock: true,
  current: null,
  loadNext: null,
  autoTimeout: null,
  mainElem: null,
  
  init: function(mainElemId, config) {
    if (typeof config == "object")
      for (var key in config)
        this.config[key] = config[key];
        
    this.mainElem = $('#' + mainElemId);
        
    /* css */
    this.mainElem.css('overflow', 'hidden');
    $('.shifter_root', this.mainElem).css('overflow', 'hidden');
    $('.shifter_root', this.mainElem).css('position', 'relative');
    $('.shifter_root', this.mainElem).css('width', this.config.bannerSize.w + 'px');
    $('.shifter_root', this.mainElem).css('height', this.config.bannerSize.h + 'px');
    $('.shifter_root', this.mainElem).css('margin-left', (-1 * Math.floor(this.config.bannerSize.w/2)) + 'px');
    $('.shifter_root', this.mainElem).css('left', '50%');
    $('.shifter_container', this.mainElem).css('position', 'absolute');
    $('.shifter_container', this.mainElem).css('left', '0');
    $('.shifter_container', this.mainElem).css('top', '0');
    $('.shifter_container', this.mainElem).css('width', (3 * this.config.bannerSize.w) + 'px');
    $('.shifter_container', this.mainElem).css('height', this.config.bannerSize.h + 'px');
    $('.shifter_buttons', this.mainElem).css('position', 'relative');
    $('.shifter_buttons', this.mainElem).css('width', (this.config.list.length * this.config.buttonSize.w) + 'px');
    $('.shifter_buttons', this.mainElem).css('height', this.config.buttonSize.h + 'px');
    
    $('.shifter_container', this.mainElem).append(this.getElement('left'));
    $('.shifter_container', this.mainElem).append(this.getElement('center'));
    $('.shifter_container', this.mainElem).append(this.getElement('right'));
    
    var cache = $(document.createElement('div')).attr('id', 'shifter_image_cache_4895795738475');
    cache.hide();
    cache.appendTo('body');
    
    for (var i=0; i<this.config.list.length; i++) {      
      $('.shifter_buttons', this.mainElem).append(this.getButton(i));
      var img = $(document.createElement('img'));
      img.attr('src', this.config.list[i].img);
      img.appendTo(cache);
    }
    
    this.select(0);
  },
  
  getElement: function(type) {
    var elem = $(document.createElement('div'));
    elem.addClass('elem');
    
    /* css */
    elem.css('float', 'left');
    elem.css('width', this.config.bannerSize.w + 'px');
    elem.css('height', this.config.bannerSize.h + 'px');
    
    var elemLnk = $(document.createElement('a'));
    elemLnk.addClass('shifter_' + type);
    elemLnk.append(elem);
    return elemLnk;
  },
  
  getButton: function(id) {
    var elem = $(document.createElement('div'));
    elem.addClass('butt');
    
    /* css */
    elem.css('float', 'left');
    elem.css('width', this.config.buttonSize.w + 'px');
    elem.css('height', this.config.buttonSize.h + 'px');
    
    elem.addClass('shifter_button_' + id);
    elem.click(function(){
      Shifter.change(id);
    });
    
    var elemDesc = $(document.createElement('span'));
    elemDesc.addClass('num');
    elemDesc.text("" + (id+1));
    elem.append(elemDesc);
    
    return elem;
  },
  
  loadItem: function(type, id) {
    $('.shifter_' + type, this.mainElem).attr('href', this.config.list[id].url);
    $('.shifter_' + type + ' div.elem', this.mainElem).css('background-image', 'url("' + this.config.list[id].img + '")');
  },
  
  select: function(id) {
    this.loadItem('center', id);
    $('.shifter_container', this.mainElem).css('left', (-1 * this.config.bannerSize.w) + 'px');
    $('.shifter_buttons .butt', this.mainElem).removeClass('selected');
    $('.shifter_button_' + id, this.mainElem).addClass('selected');
    this.current = id;
    this.lock = false;
    if (this.loadNext !== null) {
      var queuedId = this.loadNext;
      this.loadNext = null;
      this.change(queuedId);
    }
    else {
      this.autoTimeout = setInterval(function() { Shifter.auto(); }, this.config.autoTimeoutDelay);
    }
  },
  
  change: function(id) {
    if (id == this.current)
      return;
    if (this.lock) {
      this.loadNext = id;
      return;
    }
    this.lock = true;
    try {
      clearInterval(this.autoTimeout);
      this.autoTimeout = null;
    }
    catch (e) {}
    var direction = (id < this.current) ? 'left' : 'right';
    
    this.loadItem(direction, id);
    $('.shifter_container', this.mainElem).animate(
      {left: (direction=='left' ? 0 : (-2 * this.config.bannerSize.w))},
      this.config.changeAnimationTime,
      function(){
        Shifter.select(id);
      }
    );
  },
  
  auto: function() {
    this.change((this.current + 1) % this.config.list.length);
  }
}

