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
    }
});