﻿/** 
 * Checkboxes
 */

// toggles all checkboxes that matches the targets.
BF.toggleCheckboxes = function (triggers, targets, options) {
    var self = this; // scope alias
    this.options = $.extend({
        callback: function () { }, // callback to be executed after toggle is done
        checkAll: false, // check all checkboxes on init?
        clearAllMsg: 'Clear All', // label for toggle checkbox when all checkboxes are checked
        inverse: false, // should the oppposite be true? I.e. checking triggers will uncheck all boxes
        labelSelector: triggers + ' + label', // label (or text) to change messaging for master toggle
        selectAllMsg: 'Select All', // label for toggle checkbox when not all checkboxes have been selected
        uncheckAll: false // uncheck all checkboxes on init?
    }, options || {});

    this.triggers = $(triggers);
    this.targets = $(targets);
    this.labels = $(this.options.labelSelector);

    if (this.options.checkAll) {
        this.checkAll();
    } else if (this.options.uncheckAll) {
        this.uncheckAll();
    } else { 
        // do nothing 
    }

    // see if all targets are checked, if so check trigger too
    if (this.areAllChecked()) {
        if (this.options.inverse) {
            this.uncheckAll();
        } else {
            this.checkAll();
        }
    }

    // if trigger is on all targets should be checked
    if (this.triggers.attr('checked')) {
        if (this.options.inverse) {
            // except if inverse is true
            this.uncheckAll();
        } else {
            this.checkAll();
        }
    }

    this.triggers.bind('click', function (e) {
        self.toggleTrigger($(this));
    });

    // deal with slave selects being clicked (changed)
    this.targets.bind('click', function (e) {
        if (self.areAllChecked() === true) {
            if (self.options.inverse) {
                self.uncheckAll();
            } else {
                self.checkAll();
            }
            self.triggers.attr('checked', true);
        } else {
            self.triggers.attr('checked', false);
            self.labels.html(self.options.selectAllMsg);
        }
        self.changed();
    });

};

BF.toggleCheckboxes.prototype = {

    areAllChecked: function () {
        // are all checkboxes checked?
        var unchecked = this.targets.filter(':not(:checked)');
        // @TODO: check for toggles without slaves?
        if (unchecked.length > 0) {
            // no, there are unchecked checkboxes
            return false;
        } else {
            // yes
            return true;
        }
    },

    changed: function () {
        // done, call the callback function
        this.options.callback.call(this);
    },

    checkAll: function () {
        if (this.options.inverse) {
            this.triggers.attr('checked', false);
        } else {
            this.triggers.attr('checked', true);
            this.labels.html(this.options.clearAllMsg);
        }
        this.targets.attr('checked', true);
    },

    toggleTrigger: function (el) {
        if (el.attr('checked') === true && this.options.inverse !== true) {
            this.targets.attr('checked', true);
            this.labels.html(this.options.clearAllMsg);
        } else {
            this.labels.html(this.options.selectAllMsg);
            this.targets.attr('checked', false);
        }

        this.changed();

    },

    uncheckAll: function () {
        if (this.options.inverse) {
            this.triggers.attr('checked', true);
        } else {
            this.triggers.attr('checked', false);
            this.labels.html(this.options.selectAllMsg);
        }
        this.targets.attr('checked', false);
    }

};

/**
* Plugify-ing
*/
(function ($) {
    $.fn.toggleCheckboxes = function (targets, options) {
        var toggler, self = this;
        this.each(function() {
            toggler = new BF.toggleCheckboxes(self.selector, targets, options);
        });

        return toggler;
    };
})(jQuery);
