/**

*/ !function($) {

'use strict';

// Toggle constructor
function Toggle($el) {
        this.$el = $($el);
        this.targets = [];
        this.on = '';
        this.className = '';
        this.self = false;

        if(this.$el.length) {
                Gumby.debug('Initializing Toggle', $el);
                this.init();
        }
}

// Switch constructor
function Switch($el) {
        this.$el = $($el);
        this.targets = [];
        this.on = '';
        this.className = '';
        this.self = false;

        if(this.$el.length) {
                Gumby.debug('Initializing Switch', $el);
                this.init();
        }
}

// intialise toggles, switches will inherit method
Toggle.prototype.init = function() {
        var scope = this;

        // set up module based on attributes
        this.setup();

        // bind to specified event and trigger
        this.$el.on(this.on, function(e) {
                e.preventDefault();
                scope.trigger(scope.triggered);

        // listen for gumby.trigger to dynamically trigger toggle/switch
        }).on('gumby.trigger', function() {
                Gumby.debug('Trigger event triggered', scope.$el);
                scope.trigger(scope.triggered);
        // re-initialize module
        }).on('gumby.initialize', function() {
                Gumby.debug('Re-initializing '+scope.constructor, $el);
                scope.setup();
        });
};

// set up module based on attributes
Toggle.prototype.setup = function() {
        this.targets = this.parseTargets();
        this.on = Gumby.selectAttr.apply(this.$el, ['on']) || Gumby.click;
        this.className = Gumby.selectAttr.apply(this.$el, ['classname']) || 'active';
        this.self = Gumby.selectAttr.apply(this.$el, ['self']) === 'false';
};

// parse data-for attribute, switches will inherit method
Toggle.prototype.parseTargets = function() {
        var targetStr = Gumby.selectAttr.apply(this.$el, ['trigger']),
                secondaryTargets = 0,
                targets = [];

        // no targets so return false
        if(!targetStr) {
                return false;
        }

        secondaryTargets = targetStr.indexOf('|');

        // no secondary targets specified so return single target
        if(secondaryTargets === -1) {
                if(!this.checkTargets([targetStr])) {
                        return false;
                }
                return [$(targetStr)];
        }

        // return array of both targets, split and return 0, 1
        targets = targetStr.split('|');
        if(!this.checkTargets(targets)) {
                return false;
        }
        return targets.length > 1 ? [$(targets[0]), $(targets[1])] : [$(targets[0])];
};

Toggle.prototype.checkTargets = function(targets) {
        var i = 0;

        for(i; i < targets.length; i++) {
                if(targets[i] && !$(targets[i]).length) {
                        Gumby.error('Cannot find '+this.constructor.name+' target: '+targets[i]);
                        return false;
                }
        }

        return true;
};

// call triggered event and pass target data
Toggle.prototype.triggered = function() {
        // trigger gumby.onTrigger event and pass array of target status data
        Gumby.debug('Triggering onTrigger event', this.$el);
        this.$el.trigger('gumby.onTrigger', [this.$el.hasClass(this.className)]);
};

// Switch object inherits from Toggle
Switch.prototype = new Toggle();
Switch.prototype.constructor = Switch;

// Toggle specific trigger method
Toggle.prototype.trigger = function(cb) {

        Gumby.debug('Triggering Toggle', this.$el);

        var $target;

        // no targets just toggle active class on toggle
        if(!this.targets) {
                this.$el.toggleClass(this.className);

        // combine single target with toggle and toggle active class
        } else if(this.targets.length == 1) {
                this.$el.add(this.targets[0]).toggleClass(this.className);

        // if two targets check active state of first
        // always combine toggle and first target
        } else if(this.targets.length > 1) {
                if(this.targets[0].hasClass(this.className)) {
                        $target = this.targets[0];

                        // add this element to it unless gumby-self set
                        if(!this.self) {
                                $target = $target.add(this.$el);
                        }

                        $target.removeClass(this.className);
                        this.targets[1].addClass(this.className);
                } else {
                        $target = this.targets[0];

                        // add this element to it unless gumby-self set
                        if(!this.self) {
                                $target = $target.add(this.$el);
                        }

                        $target.addClass(this.className);
                        this.targets[1].removeClass(this.className);
                }
        }

        // call event handler here, applying scope of object Switch/Toggle
        if(cb && typeof cb === 'function') {
                cb.apply(this);
        }
};

// Switch specific trigger method
Switch.prototype.trigger = function(cb) {

        Gumby.debug('Triggering Switch', this.$el);

        var $target;

        // no targets just add active class to switch
        if(!this.targets) {
                this.$el.addClass(this.className);

        // combine single target with switch and add active class
        } else if(this.targets.length == 1) {
                $target = this.targets[0];

                // add this element to it unless gumby-self set
                if(!this.self) {
                        $target = $target.add(this.$el);
                }

                $target.addClass(this.className);

        // if two targets check active state of first
        // always combine switch and first target
        } else if(this.targets.length > 1) {
                $target = this.targets[0];

                // add this element to it unless gumby-self set
                if(!this.self) {
                        $target = $target.add(this.$el);
                }

                $target.addClass(this.className);
                this.targets[1].removeClass(this.className);
        }

        // call event handler here, applying scope of object Switch/Toggle
        if(cb && typeof cb === 'function') {
                cb.apply(this);
        }
};

// add toggle initialisation
Gumby.addInitalisation('toggles', function(all) {
        $('.toggle').each(function() {
                var $this = $(this);

                // this element has already been initialized
                // and we're only initializing new modules
                if($this.data('isToggle') && !all) {
                        return true;

                // this element has already been initialized
                // and we need to reinitialize it
                } else if($this.data('isToggle') && all) {
                        $this.trigger('gumby.initialize');
                }

                // mark element as initialized
                $this.data('isToggle', true);
                new Toggle($this);
        });
});

// add switches initialisation
Gumby.addInitalisation('switches', function(all) {
        $('.switch').each(function() {
                var $this = $(this);

                // this element has already been initialized
                // and we're only initializing new modules
                if($this.data('isSwitch') && !all) {
                        return true;

                // this element has already been initialized
                // and we need to reinitialize it
                } else if($this.data('isSwitch') && all) {
                        $this.trigger('gumby.initialize');
                        return true;
                }

                // mark element as initialized
                $this.data('isSwitch', true);
                new Switch($this);
        });
});

// register UI module
Gumby.UIModule({
        module: 'toggleswitch',
        events: ['initialize', 'trigger', 'onTrigger'],
        init: function() {
                // Run initialize methods
                Gumby.initialize('switches');
                Gumby.initialize('toggles');
        }
});

}(jQuery);