var Validation = {
    init: function(form) {
        this.form = $(form);
        this.inputs = this.form.find('.validate');
        this.buttons = $('a.button.next');
        this.errorMessage = $('<div class="growl relative validationMessage">Please fill out all required fields.</div>');
        this.bindEvents();
    },

    bindEvents: function() {
        var that = this;
        this.inputs.each(function() {
            var input = this;
            $(this).typeWatch({
                callback:function() {
                    if ($(input).hasClass('error')) {
                        that.removeError(input);
                        that.startValidation(this);
                    }
                },
                captureLength:5,
                wait:750
            });

            if ($(this).attr('id') == 'policy_date') {
                $(this).change(function() {
                    if ($(this).hasClass('error')) {
                        that.removeError(this);
                        that.startValidation(this);
                    }
                });
            }

            if (this.tagName == 'SELECT') {
                $(this).change(function() {
                    if ($(this).val() != '') {
                        if ($(this).hasClass('error')) {
                            that.removeError(this);
                            that.startValidation(this);
                        }
                    }
                });
            }

            if ($(this).is(':radio')) {
                $(this).change(function() {
                    that.inputs.filter(':radio').each(function() {
                        that.removeError(this);
                        that.toggleErrors(true);
                    });
                });
            }
        });
    },

    startValidation: function(target) {
        var valid = true,
                that = this;

        if (!$(target).hasClass('prev')) {
            if (!$(target).children().hasClass('checked')) {
                var error_check = [];
                $(this.inputs).each(function() {
                    if ($(this).parents('.input_container').is(':visible') && !$(this).hasClass('ignore')) {
                        has_error = that.hasError(this);
                        error_check.push(has_error);
                    }
                });

                $(error_check).each(function(error) {
                    valid = valid && error_check[error];
                });
            } else {
                valid = true;
            }
        }


        this.toggleErrors(valid);

        return valid;
    },

    hasError: function(input) {
        this.inputErrors(input);

        if (!$(input).hasClass('error')) {
            this.validationExceptions(input, $(input).attr('id'));
        }

        return !!(!$(input).hasClass('error'));
    },

    validationExceptions: function(input, id) {
        // Regex
        var email_regex = /\b[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,4}\b/,
                phone_regex = /(\D*\d\D*){10}/;

        var that = this;
        var errorMessage;
        var exceptionRules = function(regex, name, example) {
            var error = false;

            if ($(input).val().match(regex)) {
                if ($(input).val().indexOf("000") == 0) {
                    error = true;
                } else if ($(input).val().indexOf("000-000-0000") == 0) {
                    error = true;
                } else if ($(input).val().indexOf("000-0000") == 4) {
                    error = true;
                } else {
                    that.removeError(input, name);
                }

                if (error) {
                    $('.inputErrorMessage').removeClass('inputErrorMessage');
                    that.addError(input);
                    errorMessage = that.showPhoneErrorMessage(input);

                    $(input).focus(function() {
                        that.removeInputErrorMessage(errorMessage);
                    }).blur(function() {
                        that.removeInputErrorMessage(errorMessage);
                    });
                }
            } else {
                that.addError(input);
                errorMessage = that.showInputErrorMessage(input, name, example);

                $(input).focus(function() {
                    that.removeInputErrorMessage(errorMessage);
                }).blur(function() {
                    that.removeInputErrorMessage(errorMessage);
                });
            }
        };

        if (id == 'email') {
            var email = 'Email',
                    emailExample = 'abc@def.com';
            exceptionRules(email_regex, email, emailExample);
        }
        if (id == 'phone') {
            var phone = 'Phone',
                    phoneExample = '###-###-####';
            exceptionRules(phone_regex, phone, phoneExample);
        }
    },

    showInputErrorMessage: function(input, name, example) {
        var errorMessage = $('<div class="inputErrorMessage">'),
                left = $(input).offset().left + parseFloat($(input).innerWidth()) + 5,
                top = $(input).offset().top,
                message = name + ' is invalid. (example: ' + example + ')';

        errorMessage
                .appendTo('body')
                .hide()
                .text(message)
                .css({
            left:left,
            top:top,
            position:'absolute'
        })
                .fadeIn(250);

        return errorMessage;
    },

    showPhoneErrorMessage: function(input) {
        var errorMessage = $('<div class="inputErrorMessage">'),
                left = $(input).offset().left + parseFloat($(input).innerWidth()) + 5,
                top = $(input).offset().top,
                message = 'Please enter a valid phone number.';

        errorMessage
                .appendTo('body')
                .hide()
                .text(message)
                .css({
            left:left,
            top:top,
            position:'absolute'
        })
                .fadeIn(250);

        return errorMessage;
    },

    removeInputErrorMessage: function(errorMessage) {
        this.e
        $(errorMessage)
                .fadeOut(250, function() {
            $(this).remove();
        });
    },

    inputErrors: function(input) {
        var hasSpaces = new RegExp();
        hasSpaces.compile('^[\s ]*$', 'gi');

        if (hasSpaces.test(input.value) == true) {
            this.addError(input);
        } else {
            this.removeError(input);
        }

        if ($(input).is(':radio')) {
            var group = $(input).attr('name');

            if ($('input[name=\'' + group + '\']').is(':checked')) {
                this.removeError(input);
            } else {
                this.addError(input);
            }
        }
    },

    addError: function(input) {
        var parent = $(input).parents('.input_container');
        if (!$(input).hasClass('error')) {
            $(input).addClass('error');
            $(parent).addClass('error');
        }
    },

    removeError: function(input) {
        var parent = $(input).parents('.input_container');
        if ($(input).hasClass('error')) {
            $(input).removeClass('error');
            $(parent).removeClass('error');
        }
    },

    toggleErrors: function(valid) {
        if (valid) {
            this.errorMessage
                    .fadeOut(250, function() {
                $(this).detach();
            });
            this.buttons.each(function() {
                if ($(this).is(':visible')) {
                    $(this).removeClass('error');
                }
            });
        } else {
            if (!this.errorMessage.is(':visible')) {
                this.errorMessage
                        .appendTo(this.form)
                        .hide()
                        .fadeIn(250);

                this.buttons.each(function() {
                    if ($(this).is(':visible')) {
                        $(this).addClass('error');
                    }
                });
            }
        }
    },

    // for use with prev
    removeAllErrors: function() {
        var that = this;

        this.inputs.each(function() {
            that.removeError(this);
        });

        this.errorMessage.fadeOut(250, function() {
            $(this).detach();
        });

        this.buttons.removeClass('error');

        var errorMessage = $('.inputErrorMessage');
        if (errorMessage.length > 0) {
            this.removeInputErrorMessage(errorMessage);
        }
    }
};

