var Tabbed = new JS.Class({
  include: Ojay.Observable,
    
  initialize: function(tabs, options) {
    options = options || {};
    
    this.setup_toggles(tabs, options);
    
    this.tabs = Ojay(tabs).map(function(el) {
      return new this.klass.Tab(this, Ojay(el), options);
    }.bind(this));
    
    if (options.width && options.height) {
      this.width = options.width, this.height = options.height;
      Ojay(tabs).parents().at(0).setStyle({height: this.height});
    }
    
    this.toggle(0);
  },
  
  setup_toggles: function(tabs, options) {
    var self = this;
    this.toggles = [];
    
    var toggles = Ojay(Ojay.HTML.ul({className: this.klass.TOGGLES_CLASS}, function (H) {
      Ojay(tabs).children(self.klass.TOGGLE_SELECTOR).forEach(function(header, i) {
        header.hide();
        var toggle = Ojay(H.li(header.node.innerHTML)).addClass('toggle-' + i);
        if (i === 0) toggle.addClass('first');
        if (i === tabs.length - 1) toggle.addClass('last');
        self.toggles.push(toggle);
        toggle.on('click', function() { self.toggle(i); });
      });
    }));
    
    if (typeof options.width != 'undefined') toggles.setStyle({width: options.width});
    
    Ojay(tabs).parents().at(0).insert(toggles, options.position || 'before');
  },
  
  toggle: function(index, options) {
    options = options || {};
    
    if (index >= this.tabs.length) index = 0;
    if (this.current_tab == index || this.animating) return;
    
    if (typeof this.current_tab == 'undefined') {
      this.current_tab = index;
      this.toggles[index].addClass('current');
      this.tabs[index].show();
    } else {
      this.animating = true;
      this.toggles.forEach(function(toggle) { toggle.removeClass('current'); });
      this.toggles[index].addClass('current');
      this.tabs[this.current_tab].hide()._(function(self) {
        self.current_tab = index;
        self.tabs[index].show()._(function() {
          self.animating = false;
          if (options.silent !== true) self.notifyObservers('tabchange', index);
        });
      }, this);
    }
  },
  
  extend: {
    TOGGLE_SELECTOR: '.tab-toggle',
    TOGGLES_CLASS:   'tab-toggles clear',
    ANIMATE_SPEED:    0.2,
    
    Tab: new JS.Class({
      
      initialize: function(group, el, options) {
        this._wrapper = el, this.group = group;
        this.animateSpeed = options.animateSpeed || this.group.klass.ANIMATE_SPEED;
        this._wrapper.hide().setStyle({opacity: 0});
        if (this.group.height)
          this._wrapper.setStyle({position: 'absolute', top: 0, left: 0});
      },
      
      hide: function() {
        var chain = new JS.MethodChain;
        this._wrapper.animate({opacity: {to: 0}}, this.animateSpeed).hide()
        ._(function(self) { chain.fire(self); }, this)._(this);
        return chain;
      },
      
      show: function() {
        var chain = new JS.MethodChain;
        this._wrapper.show().animate({opacity: {to: 1}}, this.animateSpeed)
        ._(function(self) { chain.fire(self); }, this)._(this);
        return chain;
      }
    })
  }
});

var TabbedCarousel = new JS.Class({
  initialize: function(wrapper, options) {
    options = options || {};
    this.wrapper = Ojay(wrapper);
    this.tabs = new Tabbed(this.wrapper.descendants(this.klass.TAB_SELECTOR),
      {width: options.width || this.wrapper.getWidth() + 'px',
       height: options.height ||
        this.wrapper.descendants('.carousel-item').at(0).getHeight()
        + (this.klass.OFFSETS[1] * 2) + 'px'});
    this.pagers = [];
    this.addCarousels(options);
    this.setupListeners();
    this.pagers[0].setup().addControls('before');
    this.wrapper.descendants('.page').forEach(function(page) {
      page.children('.carousel-item').at(0).addClass('carousel-item-first');
    });
  },
  
  addCarousels: function(options) {
    this.wrapper.descendants(this.klass.CAROUSEL_SELECTOR)
    .forEach(function(cwrap) {
      var paginator = new Ojay.Paginator(cwrap,
        {columns: options.columns || 3, rows: options.rows || 1});
      this.pagers.push(paginator);
    }.bind(this));
  },
  
  setupListeners: function() {
    this.tabs.on('tabchange', function(tabs, index) {
      if (!this.pagers[index]) return;
      
      this.pagers[index].setup().addControls('before');
      
      this.wrapper.descendants('.page').forEach(function(page) {
        page.children('.carousel-item').at(0).addClass('carousel-item-first');
      });
      
      delete pagers[index];
    }, this);
  },
  
  extend: {
    TAB_SELECTOR: '.tab',
    CAROUSEL_SELECTOR: '.carousel',
    OFFSETS: [29, 16]
  }
});

var TabbedPromotion = new JS.Class({
  initialize: function(wrapper, options) {
    options = options || {};
    this.wrapper = Ojay(wrapper);
    
    this.tabbed = new Tabbed(
      this.wrapper.descendants(this.klass.TAB_SELECTOR),
      options);
    
    this.tabbed.on('tabchange', function(tabs, index) {
      this.interval = this.klass.INTERVAL * 2;
      this.lastChanged = Number(new Date);
    }, this);
    
    this.setupTransitions();
  },
  
  setupTransitions: function() {
    this.interval = this.klass.INTERVAL;
    this.lastChanged = Number(new Date);
    
    setInterval(function() {
      var time = Number(new Date);
      if (time - this.lastChanged > this.interval) {
        this.lastChanged = time;
        this.interval = this.klass.INTERVAL;
        this.tabbed.toggle(this.tabbed.current_tab + 1, {silent: true});
      }
    }.bind(this), 250);
  },
  
  extend: {
    TAB_SELECTOR: '.tab',
    INTERVAL:      15000
  }
});

