﻿/**
* Expand / Collapse - show and hide targets
* @param triggers {string}
* @param targets {string}
* @param options {object}
*/
BF.expandCollapse = function (triggers, targets, options) {

    // scope alias
    var self = this;

    // setup defaults
    this.options = $.extend({
        animate: true, // animate or not?
        animationDuration: 100, // time (in milliseconds) it takes to animate
        beforeSetup: function () { }, // callback function that runs before 
        collapseClass: 'collapsed', // set a class on the target
        defaultCollapse: true, // should the targets be collapsed by default?
        master: null, // selector of master (all) trigger
        masterShowMsg: 'Show All [+]', // master message when all collapsed
        masterHideMsg: 'Hide All [-]', // master message when all expanded 
        showMsg: '[+]', // trigger message when target is collapsed
        hideMsg: '[-]' // trigger message when target is expanded
    }, options || {});

    this.options.beforeSetup.call(this);

    if ($.support.opacity === false) {
        // if browser doesn't support opacity, turn animations off
        this.options.animate = false;
    }

    this.triggers = $(triggers);
    this.targets = $(targets);

    if (this.options.defaultCollapse) {
        this.targets.hide().addClass(this.options.collapseClass);
        this.triggers.html(this.options.showMsg);
    } else {
        this.triggers.html(this.options.hideMsg);
    }

    // events
    this.triggers.bind('click', function (e) {
        e.preventDefault();
        var index = self.triggers.index(this);
        self.toggle(index);
    });

    if (this.options.master) {
        this.master = $(this.options.master);
        this.master.bind('click', function (e) {
            e.preventDefault();
            var test = self.allVisible();
            if (test === true) {
                self.collapseAll();
            } else {
                self.expandAll();
            }
        });
        if (this.options.defaultCollapse === false) {
            this.master.html(this.options.masterHideMsg);
        } else {
            this.master.html(this.options.masterShowMsg);
        }
    }
    this.setHide = function (target, index) {
        target.hide().addClass(this.options.collapseClass);
        this.triggers.eq(index).html(this.options.showMsg);
        if (this.options.master) {
            // check if all are visible, if so change message on master
            if (this.allVisible()) {
                this.master.html(this.options.masterHideMsg);
            } else {
                this.master.html(this.options.masterShowMsg);
            }
        }
    };

    this.setShow = function (target, index) {
        target.show().removeClass(this.options.collapseClass);
        this.triggers.eq(index).html(this.options.hideMsg);
        if (this.options.master) {
            // check if all are visible, if so change message on master
            if (this.allVisible()) {
                this.master.html(this.options.masterHideMsg);
            } else {
                this.master.html(this.options.masterShowMsg);
            }
        }
    };

};

BF.expandCollapse.prototype = {

    allVisible: function () {
        if (this.targets.filter(':visible').length === this.targets.length) {
            return true;
        } else {
            return false;
        }
    },

    collapse: function (index) {
        var self = this,
            target = this.targets.eq(index);

        if (this.options.animate) {
            target.fadeTo(this.options.animationDuration, 0, function (e) {
                self.setHide(target, index);
            });
        } else {
            this.setHide(target, index);
        }
    },

    expand: function (index) {
        var self = this,
            target = this.targets.eq(index);

        if (this.options.animate) {
            target.fadeTo(this.options.animationDuration, 1, function (e) {
                self.setShow(target, index);
            });
        } else { 
            this.setShow(target, index);
        }



    },

    toggle: function (index) {
        // toggle open (visible) and closed
        if (this.targets.eq(index).is(':visible')) {
            this.collapse(index);
        } else {
            this.expand(index);
        }
    },

    collapseAll: function () {
        // collapse all targets
        for (var i = 0, l = this.targets.length; i < l; i++) {
            this.collapse(i);
        }
    },

    expandAll: function () {
        // expand all targets
        for (var i = 0, l = this.targets.length; i < l; i++) {
            this.expand(i);
        }
    }

};

/**
 * Plugify-ing
 */ 
(function ($) { 
    $.fn.expandCollapse = function(targets, options) {   
        var exCo = new BF.expandCollapse(this.selector, targets, options);      
        return exCo;
    };
})(jQuery);
