(function(window, $, undefined) {

/*
  * smartresize: debounced resize event for jQuery
  *
  * latest version and complete README available on Github:
  * https://github.com/louisremi/jquery.smartresize.js
  *
  * Copyright 2011 @louis_remi
  * Licensed under the MIT license.
  */

    var $event = $.event,
        resizeTimeout;

    $event.special.smartresize = {
        setup: function() {
            $(this).bind("resize", $event.special.smartresize.handler);
        },
        teardown: function() {
            $(this).unbind("resize", $event.special.smartresize.handler);
        },
        handler: function(event, execAsap) {
            // Save the context
            var context = this,
                args = arguments;

            // set correct event type
            event.type = "smartresize";

            if (resizeTimeout) {
                clearTimeout(resizeTimeout);
            }
            resizeTimeout = setTimeout(function() {
                jQuery.event.handle.apply(context, args);
            }, execAsap === "execAsap" ? 0 : 100);
        }
    };

    $.fn.smartresize = function(fn) {
        return fn ? this.bind("smartresize", fn) : this.trigger("smartresize", ["execAsap"]);
    };

    $.Accordion = function(options, element) {

        this.$el = $(element);
        // list items
        this.$items = this.$el.children('ul').children('li');
        // total number of items
        this.itemsCount = this.$items.length;

        // initialize accordion
        this._init(options);

    };

    $.Accordion.defaults = {
        // index of opened item. -1 means all are closed by default.
        open: -1,
        // if set to true, only one item can be opened. Once one item is opened, any other that is opened will be closed first
        oneOpenedItem: false,
        // speed of the open / close item animation
        speed: 600,
        // easing of the open / close item animation
        easing: 'easeInOutExpo',
        // speed of the scroll to action animation
        //scrollSpeed: 900,
        // easing of the scroll to action animation
       // scrollEasing: 'easeInOutExpo'
    };

    $.Accordion.prototype = {
        _init: function(options) {

            this.options = $.extend(true, {}, $.Accordion.defaults, options);

            // validate options
            this._validate();

            // current is the index of the opened item
            this.current = this.options.open;

            // hide the contents so we can fade it in afterwards
            this.$items.find('div.st-content').hide();

            // save original height and top of each item  
            this._saveDimValues();

            // if we want a default opened item...
            if (this.current != -1) this._toggleItem(this.$items.eq(this.current));

            // initialize the events
            this._initEvents();

        },
        _saveDimValues: function() {

            this.$items.each(function() {

                var $item = $(this);

                $item.data({
                    originalHeight: $item.find('a:first').height(),
                    offsetTop: $item.offset().top + 40 + "px"
                });

            });

        },
        // validate options
        _validate: function() {

            // open must be between -1 and total number of items, otherwise we set it to -1
            if (this.options.open < -1 || this.options.open > this.itemsCount - 1) this.options.open = -1;

        },
        _initEvents: function() {

            var instance = this;

            // open / close item
            this.$items.find('a:first').bind('click.accordion', function(event) {

                var $item = $(this).parent();

                // close any opened item if oneOpenedItem is true
                if (instance.options.oneOpenedItem && instance._isOpened() && instance.current !== $item.index()) {

                    instance._toggleItem(instance.$items.eq(instance.current));

                }

                // open / close item
                instance._toggleItem($item);

                return false;

            });

            $(window).bind('smartresize.accordion', function(event) {

                // reset orinal item values
                instance._saveDimValues();

                // reset the content's height of any item that is currently opened
                instance.$el.find('li.st-open').each(function() {

                    var $this = $(this);
                    $this.css('height', $this.data('originalHeight') + $this.find('div.st-content').outerHeight(true));

                });

                // scroll to current
                // if (instance._isOpened()) instance._scroll();

            });

        },
        // checks if there is any opened item
        _isOpened: function() {

            return (this.$el.find('li.st-open').length > 0);

        },
        // open / close item
        _toggleItem: function($item) {

            var $content = $item.find('div.st-content');

            ($item.hasClass('st-open'))

            ? (this.current = -1, $content.stop(true, true).fadeOut(this.options.speed), $item.removeClass('st-open').stop().animate({
                height: $item.data('originalHeight')
            }, this.options.speed, this.options.easing))

            : (this.current = $item.index(), $content.stop(true, true).fadeIn(this.options.speed), $item.addClass('st-open').stop().animate({
                height: $item.data('originalHeight') + $content.outerHeight(true)
            }, this.options.speed, this.options.easing)/*, this._scroll(this)*/)

        },
        // scrolls to current item or last opened item if current is -1
        /*_scroll: function(instance) {
   var instance = instance || this,
                current;

            (instance.current !== -1) ? current = instance.current : current = instance.$el.find('li.st-open:last').index();

            $('html, body').stop().animate({
                scrollTop: (instance.options.oneOpenedItem) ? instance.$items.eq(current).data('offsetTop') : instance.$items.eq(current).offset().top + 40 + "px"
            }, instance.options.scrollSpeed, instance.options.scrollEasing);

        }*/
    };

    var logError = function(message) {

        if (this.console) {

            console.error(message);

        }

    };

    $.fn.accordion = function(options) {

        if (typeof options === 'string') {

            var args = Array.prototype.slice.call(arguments, 1);

            this.each(function() {

                var instance = $.data(this, 'accordion');

                if (!instance) {
                    logError("cannot call methods on accordion prior to initialization; " + "attempted to call method '" + options + "'");
                    return;
                }

                if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
                    logError("no such method '" + options + "' for accordion instance");
                    return;
                }

                instance[options].apply(instance, args);

            });

        }
        else {

            this.each(function() {
                var instance = $.data(this, 'accordion');
                if (!instance) {
                    $.data(this, 'accordion', new $.Accordion(options, this));
                }
            });

        }

        return this;

    };

})(window, jQuery);

