/*global jQuery */

"use strict";

(function($) {
    function Checkbox(checkbox, conf, checkhandler, uncheckhandler) {
        var publ = {}, priv = {};


        priv.defaults = {
            styledCheckboxClass: 'styledCheckbox'
        };


        priv.init = function(checkbox, conf) {
            priv.initVariables();

            priv.storeSettings(conf);
            priv.storeElements(checkbox);

            priv.main();
        };


        priv.initVariables = function() {
            priv.settings = null;
            priv.checkbox = null;
            priv.label = null;
            priv.styledCheckbox = null;
            priv.checkboxState = null;
        };


        priv.storeSettings = function(conf) {
            priv.settings = $.extend(priv.defaults, conf);

            priv.settings.styledCheckboxSelector = '.' + priv.settings.styledCheckboxClass;
        };


        priv.storeElements = function(checkbox) {
            priv.checkbox = $(checkbox);
            priv.label = $('label[for=' + priv.checkbox.attr('id') + ']');
        };


        priv.main = function() {
            priv.createStyledCheckbox();
            priv.storeStyledCheckbox();
            priv.checkbox.hide();

            priv.addEventHandlers();
        };


        priv.createStyledCheckbox = function() {
            priv.checkbox.wrap('<div class="' + priv.settings.styledCheckboxClass + '" />').wrap('<div class="' + priv.getCheckboxState() + '" />');
        };


        priv.getCheckboxState = function() {
            if (priv.checkbox.attr('checked')) {
                return 'checked';
            }
            return 'unchecked';
        };


        priv.storeStyledCheckbox = function() {
            priv.styledCheckbox = priv.checkbox.closest(priv.settings.styledCheckboxSelector);
            priv.checkboxState = priv.checkbox.parent();
        };


        priv.addEventHandlers = function() {
            priv.styledCheckbox.add(priv.label).bind('click', function() {
                publ.toggle();
                return false;
            });
        };


        publ.toggle = function() {
            if (priv.getCheckboxState() === 'checked') {
                publ.uncheck();
            } else {
                publ.check();
            }
        };


        publ.check = function() {
            priv.checkbox.attr('checked', true);
            priv.checkboxState.addClass('checked').removeClass('unchecked');
            // if the checkhandler is passed in when object initialized, call
            if (checkhandler)
                checkhandler($(checkbox));
        };


        publ.uncheck = function() {
            priv.checkbox.attr('checked', false);
            priv.checkboxState.removeClass('checked').addClass('unchecked');
            // if the uncheckhandler is passed in when object initialized, call
            if (uncheckhandler)
                uncheckhandler($(checkbox));
        };

        priv.init(checkbox, conf);

        publ.checked = function() {
            return priv.checkboxState.hasClass('checked');
        };

        publ.getCore = function() {return priv.checkbox};

        return publ;
    }

    // Nathan: add addition param "checkhandler" function ref which called when checked is called
    $.fn.styledCheckbox = function(conf, checkhandler, uncheckhandler) {
        var instances = [];

        this.each(function() {
            instances.push(new Checkbox(this, conf, checkhandler, uncheckhandler));
        });

        return (instances.length === 1) ? instances[0] : instances;
    };
} (jQuery));
