// Inspired by base2 and Prototype
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};

  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);
            this._super = tmp;

            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
  };
})();
/**
* This is the base class for ajax forms which reveal themselves upon clicking (or focusing, if text input) on a trigger.
* @param string wrapper(ex. '#someid') - Wraps the form
* @param string trigger(ex. '#sometrigger') - Triggers the form display
* @var body(jquery Obj) - The document's body element
* @var wrapper(jquery Obj) - The designated form wrapper
* @var error(jquery Obj) - Error message div
* @var success(jquery Obj) - Success message div(must be id of '#' + wrapperid + 'success').  This allows you to put the success message outside of the wrapper
* @var loader(jquery Obj) - Loading gif(must be class of '.ssloader')
* @var form(jquery Obj) - The form element (.ssform)
* @var close(jquery Obj) - Link to close the form (.ssclose)
* @var required(jquery Obj) - Fields that are required (.ssrequired)
* @var optional(jquery Obj) - Fields that are optional
* @var emails(jquery Obj) - Fields that are emails; will be validated (.ssemail)
* @var inputs(jquery Obj) - All inputs
* @var textInputs(jquery Obj) - All text inputs
* @var trig(jquery Obj) - Element that triggers the form
* @var string msg - Error or success message
* @var bool display - Tells whether form is currently displayed/expanded
* @var array initialVals - Stores the inital values of the text fields
*/
var SpiffySignup = Class.extend({
    init: function(wrapper,trigger,position,transition,valhelper){
       
        this.wrapper = $(wrapper);
        this.trig = $(trigger);
        this.position = position || 'top';
        this.transition = transition || 'slide';
        this.valhelper = valhelper;
       
        this.body = $('body');
        this.error = $(wrapper + ' .sserror');
        this.success = $('#'+this.wrapper.attr('id')+'success');
        this.loader = $(wrapper + ' .ssloader');
        this.form = $(wrapper + ' .ssform');
        this.close = $(wrapper + ' .ssclose');
        this.required = $(wrapper + ' .ssrequired');
        this.optional = $(wrapper + ' :input:not(:hidden)').not(':submit').not('.ssrequired');
        this.emails = $(wrapper + ' .ssemail');
        this.inputs = this.form.find(':input');
        this.textInputs = this.form.find(':text');
        this.msg = '';
        this.display = 0;
        this.focuselement = $(wrapper + ' .ssfocus');
        this.errorFields = new Array();
        this.closeTimer = null;
        this.initialVals = [];
        this.activateTrigger();
        this.activateClose();
        this.activateSubmit();
        this.bindResize();
        this.bindScroll();
        if(this.valhelper == true){
            this.getInitialValues();
            this.activateInputs();
        }
    },
    showLoader: function() {
        this.loader.show();
    },
    hideLoader: function() {
        this.loader.hide();
    },
    parseMessage: function(msg) {
        return msg.replace(/_/g,' ');
    },
    updateDisplayStatus: function() {
        if(this.display == 0){this.display = 1;}
        else {this.display = 0;}
    },
    getInitialValue: function(obj){
        return this.initialVals[obj.attr('id')];
    },
    getInitialValues: function() {
        var me = this;
        $.each(me.textInputs, function() {
                me.initialVals[$(this).attr('id')] = $(this).val();
        });
    },
    resetInitialValue: function(obj) {
        var iv = this.getInitialValue(obj);
        obj.val(iv);
    },
    clearValue: function(obj) {
        obj.val('');
    },
    checkInitialValue: function(obj) {
        var iv = this.getInitialValue(obj);
        if(obj.val() == iv) {
            this.clearValue(obj);
        }
        else if(obj.val() === '') {
            this.resetInitialValue(obj);
        }
    },
    setBlur: function(obj) {
        var me = this;
        obj.bind('blur',function() {
            me.checkInitialValue($(this));
        });
    },
    setFocus: function(obj) {
        var me = this;
        obj.bind('focus',function() {
            me.checkInitialValue($(this));
        });
    },
    bindScroll:function() {
    		var me = this;
    		$(window).bind('scroll',function() {
            if(me.display == 1) {
            		clearTimeout(me.scrollTimer);
            		var closure = function() {
            			me.repositionElements();	
            		}
            		me.scrollTimer = setTimeout(closure,200);
            }
        });
    },
    bindResize: function() {
        var me = this;
        $(window).bind('resize',function() {
            if(me.display == 1) {
                me.repositionElements();
            }
        });
    },
    activateInputs: function() {
        var me = this;
        $.each(me.textInputs, function() {
             if($(this).attr('id')!= me.trig.attr('id')) {
                 me.setFocus($(this));
                 me.setBlur($(this));
             }
        });
    },
    activateTrigger: function() {
        var me = this;
        var bind = 'click';
        if(this.trig.is("INPUT")) {
            bind = 'focus';
            me.setBlur(me.trig);
        }
        this.trig.bind(bind, function() {
                if(bind == 'focus' && me.valhelper == true){
                    me.checkInitialValue($(this));
                }
                if(me.display == 0){me.displayForm();}
                return false;
        });
    },
    activateSubmit: function() {
        var me = this;
        this.form.submit(function() {
            me.clearMessages();
            if(!me.validateFields()){return false;}
            me.clearOptionalFields();
            me.showLoader();
            $.ajax({
                type: "POST",
                url: $(this).attr('action'),
                data: me.inputs.serialize(),
                success: function(ret) {
                    me.hideLoader();
                    me.resetOptionalFields();
                    if(me.isErrorResponse(ret)) {
                    		me.msg = 'Your submission was not successful.  Please try again.';
                        me.displayErrorMessage();   
                    }
                    else {
                        me.displaySuccessMessage();
                        me.resetAllFields();
                    }
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    me.hideLoader();
                    me.msg = 'This request did not work ' + textStatus + errorThrown;
                    me.displayErrorMessage();
                }
            });
            return false;
        });
    },
    isErrorResponse:function(r) {
    	var re = new RegExp("<!--ERROR-->");
    	return re.exec(r);
    },
    activateClose: function() {
        var me = this;
        this.close.bind('click',function(){
            if(me.closeTimer != null) {
                clearTimeout(me.closeTimer);
            }
            me.closeForm();
        });
    },
    clearMessages: function() {
        this.msg = '';
        this.success.hide();
        this.loader.hide();
        this.error.empty();
        this.error.hide();
        this.removeErrorHighlights();
    },
    clearOptionalFields: function() {
        var me = this;
        $.each(this.optional, function() {
            if($(this).val() == me.getInitialValue($(this))) {
                me.clearValue($(this));
            }
        });
    },
    resetOptionalFields: function() {
        var me = this;
        $.each(this.optional, function() {
            if($(this).val() == '') {
                me.resetInitialValue($(this));
            }
        });
    },
    resetAllFields: function() {
        var me = this;
        $.each(this.textInputs, function() {
            me.resetInitialValue($(this));
        });
    },
    validateEmail: function(email) {
        var myregex = new RegExp('^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([0-9]{1,3})|([a-zA-Z]{2,3})|(aero|coop|info|museum|name))$');
        var result = email.match(myregex);
        if(result && result[0] == email){return true;}
        else {return false;}
    },
    verifyEmail: function(obj) {
        var verifier = $("#verify_"+obj.attr('name'));
        if(verifier.id != undefined){
            if(obj.val() == verifier.val()) {
                return true;
            }
            else {return false;}
        }
        return true;
    },
    validateFields: function() {
        var me = this;
        var error = false;
        $.each(this.required, function() {
            var iv = me.getInitialValue($(this));
            var trimval = $.trim($(this).val());
            if(trimval == '') {
                me.errorFields.push($(this));
                error = true;
            }
            else if($(this).val() == iv && iv !== '') {
                me.errorFields.push($(this));
                error = true;
            }
        });
        if(error == true) {me.msg += "Please fill in the highlighted fields.<br />";}
        $.each(this.emails, function() {
            if(!me.validateEmail($(this).val())){
                me.msg += "Your email is invalid.<br />";
                me.errorFields.push($(this));
                error = true;
            }
            if(!me.verifyEmail($(this))) {
                me.msg += "Your emails do not match.";
                me.errorFields.push($(this));
                me.errorFields.push($("#verify_"+$(this).attr('name')));
                error = true;
            }
           
        });
        if(error) {
            me.displayErrorMessage();
            return false;
        }
        else {return true;}
    },
    displaySuccessMessage: function() {
        var me = this;
        this.success.show();
    },
    displayErrorMessage: function() {
        var msg = this.parseMessage(this.msg);
        this.error.append(msg);
        this.highlightErrorFields();
        this.error.show();
        this.repositionElements();
    },
    highlightErrorFields: function() {
        $.each(this.errorFields,function() {
            $(this).addClass("inputerror");
        });
    },
    removeErrorHighlights: function() {
        $.each(this.errorFields,function() {
            $(this).removeClass("inputerror");
        });
        this.errorFields = new Array();
    },
    toggleForm: function() {
        switch(this.transition) {
            case 'slide':
                this.wrapper.animate({height: 'toggle',opacity: 'toggle'},500,'swing');
                break;
            case 'fade':
                this.wrapper.animate({opacity: 'toggle'},150,'swing');
                break;
            default:
                break;
        }   
        this.updateDisplayStatus();
    },
    displayForm: function() {
        var me = this;
        if(this.display == 0) {
            this.repositionElements();
            this.toggleForm();
            var closure = function() {
                me.focuselement.focus();
            }
            setTimeout(closure,500);
        }
    },
    closeForm: function() {
        var me = this;
        if(this.display == 1){
            this.toggleForm();
            this.trig.unbind();
            this.clearMessages();
            this.activateTrigger();
            var closure = function() {
                me.form.show();
            }
            setTimeout(closure,500);
        }
    },
    addOpaqueLayerDiv: function() {
        this.body.append("<div id='opaquelayer'></div>");
        this.ol = $('#opaquelayer');
        this.ol.css({
            minWidth:'100%',
            minHeight:'100%',
            height:'100%',
            opacity:'0.5',
            backgroundColor:'#000000',
            zIndex:'100',
            position:'absolute',
            top:'0',
            left:'0',
            margin:'0',
            padding:'0',
            display:'none'
        });
    },
    toggleOpaqueLayer: function() {
        this.ol.animate({opacity:'toggle'},50,'linear');
    },
    repositionElements: function() {
        this.findWinHeight();
        this.findDocHeight();
        this.findWrapHeight();
        this.findScrollTop();
        this.findDistFromTop();
        /*this.repositionOpaqueLayer();*/
        this.repositionWrapper();
    },
    findWinHeight: function() {
        this.winHeight = $(window).height();
    },
    findDocHeight: function() {
        this.docHeight = $(document).height();
    },
    findScrollTop: function() {
        this.scrollTop = $(window).scrollTop();
    },
    findWrapHeight: function() {
        this.wrapHeight = this.wrapper.height();
    },
    repositionOpaqueLayer: function() {
        var h = this.docHeight;
        this.ol.css('height',h+'px');
    },
    repositionWrapper: function() {
            if(this.position == 'center') {
                this.wrapper.css({
                    position:'relative',
                    margin: this.fromTop+'px auto 0 auto'
                });
            }
    },
    findDistFromTop: function() {
        var dist = 0;
        if(this.winHeight > this.wrapHeight && this.position != 'top'){
            var diff = this.winHeight - this.wrapHeight;
            dist = Math.floor((diff-5)/2);
        }
        this.fromTop = dist + this.scrollTop;
    }   
});


/*************************************/


var LightboxSignup = SpiffySignup.extend({
    init: function(wrapper,trigger,position,transition,valhelper) { //location is center or top,transition is slide or fade in/out
        this._super(wrapper,trigger,position,transition,valhelper);
        this.addExtraWrapper();
        /*this.addOpaqueLayerDiv();*/
        this.applyCss();
    },
    addExtraWrapper: function() {
        this.wrapper.wrap("<div id='"+this.wrapper.attr('id')+"extrawrapper'></div>");
        this.extrawrapper = $("#"+this.wrapper.attr('id')+"extrawrapper");
        this.success.wrap("<div id='"+this.success.attr('id')+"extrawrapper'></div>");
        this.successwrapper = $("#"+this.success.attr('id')+"extrawrapper");
    },
    applyCss: function() {
        switch(this.position) {
           case 'center':
                /*this.wrapper.css({
                    position:'relative',
                    margin:this.fromTop+'px auto'
                });*/
                this.success.css({
                    margin:'auto'
                });
                break;
            case 'top':
                this.wrapper.css({
                    position:'relative',
                    margin:'0px auto'
                });
                break;
        }
        this.extrawrapper.css({
                    position:'absolute',
                    top:'0',
                    left:'0',
                    width:'100%',
                    zIndex:'1000'
        });
    },
    displayForm: function() {
        if(this.display == 0) {
            this._super();
            /*this.toggleOpaqueLayer();*/
        }
    },
    closeForm: function() {
        if(this.display == 1) {
            this._super();
            /*this.toggleOpaqueLayer();*/
        }
    },
    displaySuccessMessage: function() {
        var me = this;
        var msg = this.parseMessage(this.msg);
        this.success.append(msg);
        this.form.hide();
        this.success.show();
        var closure = function() {
            me.closeForm();
        }
        this.closeTimer = setTimeout(closure,3000);
    }
});



/***************************/


var DropdownSignup = SpiffySignup.extend({
    init: function(wrapper,trigger,position,transition) {
        this._super(wrapper,trigger,position,transition);
        this.additional = $(wrapper + ' .ssadditional');
        this.additional.hide();
        /*this.addOpaqueLayerDiv();*/
    },   
    toggleForm: function() {
        this.additional.animate({height: 'toggle',opacity: 'toggle'},500,'swing');
        if(this.close.css('display') == 'none'){this.close.css('display','block');}
        else{this.close.css('display','none');}
        this.updateDisplayStatus();
    }
});


