/**
 * Form Validator Class
 */
var FormValidator = Class.create( {
    /**
     * Constructor for this class
     *
     * @author Myoungseok, Seo
     * @param targetFormName
     */
    initialize : function(targetForm) {
        this.targetForm = targetForm;
        this.checkerList = [];
    },

    /**
     * get target form name
     */
    getFormName : function() {
        return this.targetForm;
    },

    /**
     * execute form validation
     */
    validate : function() {
        for ( var index = 0, length = this.checkerList.length ; index < length ; index++ ) {
            var fieldChecker = this.checkerList[index];
            if ( fieldChecker.check() == false ) {
                alert(fieldChecker.getErrorMessage());
                if ( fieldChecker.isFocus() ) {
					var target_elements = this.targetForm[fieldChecker.getFieldName()];
					
					if( target_elements.length > 1 )
						target_elements[0].focus();
					else
						target_elements.focus();
						
                } /*else {
                    document.location.href = fieldChecker.getRedirect();
                }*/
                return false;
            }
        }
        return true;
    },

    /**
     * validate required field
     */
    checkRequired : function(fieldName, errorMessage, focus, label) {
        this.checkerList.push(
                new RequiredFieldChecker(this.targetForm, fieldName, errorMessage, focus, label));
    },

    /**
     *
     */
    checkMaxLength : function(fieldName, maxLength, errorMessage, focus, label) {
        this.checkerList.push(
                new MaxLengthFieldChecker(this.targetForm, fieldName,
                        maxLength, errorMessage, focus, label));
    },

    /**
     *
     */
    checkMaxLengthByte : function(fieldName, maxLength, errorMessage, focus, label) {
        this.checkerList.push(
                new MaxLengthByteFieldChecker(this.targetForm, fieldName,
                        maxLength, errorMessage, focus, label));
    },

    /**
     *
     */
    checkMinLength : function(fieldName, minLength, errorMessage, focus, label) {
        this.checkerList.push(
                new MinLengthFieldChecker(this.targetForm, fieldName,
                        minLength, errorMessage, focus, label));
    },

    /**
     *
     */
    checkMinLengthByte : function(fieldName, minLength, errorMessage, focus, label) {
        this.checkerList.push(
                new MinLengthByteFieldChecker(this.targetForm, fieldName,
                        minLength, errorMessage, focus, label));
    },

    checkRegex : function(fieldName, regex, errorMessage, focus, label) {
        this.checkerList.push(
                new RegexFieldChecker(this.targetForm, fieldName,
                        regex, errorMessage, focus, label));
    },

    checkAlphaNum : function(fieldName, errorMessage, focus, label) {
        this.checkerList.push(
                new RegexFieldChecker(this.targetForm, fieldName,
                        /^[a-zA-Z0-9]+$/, errorMessage, focus, label));
    },

    checkOnlyNumber : function(fieldName, errorMessage, focus, label) {
        this.checkerList.push(
                new RegexFieldChecker(this.targetForm, fieldName,
                        /^[0-9]+$/, errorMessage, focus, label));
    },

    checkDecimal : function(fieldName, errorMessage, focus, label) {
        this.checkerList.push(
                new RegexFieldChecker(this.targetForm, fieldName,
                        /^(\-)?[0-9]*(\.[0-9]*)?$/, errorMessage, focus, label));
    },

    checkEmail : function(fieldName, errorMessage, focus, label) {
        this.checkerList.push(
                new RegexFieldChecker(this.targetForm, fieldName,
                        /^((\w|[\-\.])+)@((\w|[\-\.])+)\.([A-Za-z]+)$/, errorMessage, focus, label));
    },

    checkSelected : function(fieldName, firstIdx, errorMessage, focus, label) {
        this.checkerList.push(
                new SelectionFieldChecker(this.targetForm, fieldName,
                        firstIdx, errorMessage, focus, label));
    },

    checkAtLeastOneChecked : function(fieldName, errorMessage, focus, label) {
        this.checkerList.push(
                new AtLeastOneCheckFieldChecker(this.targetForm, fieldName,
                        errorMessage, focus, label));
    },

	checkVersion : function(fieldName, errorMessage, focus, label) {
        this.checkerList.push(
                new RegexFieldChecker(this.targetForm, fieldName,
                        /^[0-9]+\.[0-9]+$/, errorMessage, focus, label));
    },
    
    /* Form Object's all field value check */
    checkPermittedPattern : function(errorMessage) {
    	// 금지 기호 : #, ;, *, {, }, <, >, &, ./, ../ 와 같은 아홉가지 패턴 
    	// (../는 ./ 포함되어 있기 때문에 별도로 추가하지 않음.)
        var prohibitedRegExp = /[#;\*{}<>&]|\.\//;	
                
        /* Validation check For Input Tag, exclude type='radio' */
        var _Input = this.targetForm.getElementsByTagName("INPUT");
        for (var i=0;i < _Input.length ; i++)
        {
            if ( _Input[i].type != 'radio' && _Input[i].type != 'checkbox'){
                //alert("<input> name : " + _Input[i].name);
                this.checkerList.push(
                new ProhibitedPatternChecker(this.targetForm, _Input[i].name,
                		prohibitedRegExp, errorMessage, _Input[i], ""));
            }
        }

        /* Validation check For Select Tag */ 
        var _Select = this.targetForm.getElementsByTagName("SELECT");
        for (var j=0;j < _Select.length ; j++)
        {
            //alert("<select> name : " + _Select[j].name);
            this.checkerList.push(
                new ProhibitedPatternChecker(this.targetForm, _Select[j].name,
                		prohibitedRegExp, errorMessage, _Select[j], ""));      
        }

        /* Validation check For Textarea Tag */
        var _Textarea = this.targetForm.getElementsByTagName("TEXTAREA");
        for (var k=0;k < _Textarea.length ; k++)
        {
            //alert("<textarea> name : " + _Textarea[k].name);
            this.checkerList.push(
                new ProhibitedPatternChecker(this.targetForm, _Textarea[k].name,
                		prohibitedRegExp, errorMessage, _Textarea[k], ""));
        }
    }
});

function getValidatorErrorMsg(msg, label)
{
	if(label)
		return label + ' : ' + msg;
	else
		return msg;
}
/**
 * Define a FieldChecker Module Class
 */
var FieldChecker = {
    getFieldName : function() {
        return this.fieldName;
    },
    getErrorMessage : function() {
        return this.errorMessage;
    },
    isFocus : function() {
        return this.focus;
    },
    getRedirect : function() {
        return this.redirect;
    }
};

/* 금지 패턴체크 : 금지된 문자가 있는지 체크함 */
var ProhibitedPatternChecker = Class.create(FieldChecker, {
    initialize : function(form, fieldName, regex, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
        this.regex = regex;
        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
        this.focus = focus;
    },

    getRegex: function() {
        return this.regex;
    },

    check : function() {
    	var field = getCheckField(this);
    	
    	if ( !field || !field.value ) {
    		return true;
    	}

    	var str = getCheckField(this).value;
        if (str.length == 0) {
            return true;
        }
        return ( str.search(this.regex) == -1 );
    }
});

/**
 * Required Field Checker Class
 */
var RequiredFieldChecker = Class.create(FieldChecker, {

    /**
     * Constructor for this class
     *
     * @param form          target form instance
     * @param fieldName     target field name
     * @param errorMessage  custom error message
     * @param focus         whether or not field focusing
     */
    initialize : function(form, fieldName, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
		this.errorMessage = getValidatorErrorMsg(errorMessage, label);
        this.focus = focus;
    },

    check : function() {
        return ( this.form[this.fieldName].value != '' );
    }

});


/**
 * Sql Injection Checker Class
 */
var SqlInjectionFieldChecker = Class.create(FieldChecker, {

    /**
     * Constructor for this class
     *
     * @param form          target form instance
     * @param fieldName     target field name
     * @param errorMessage  custom error message
     * @param focus         whether or not field focusing
     */
    initialize : function(form, fieldName, errorMessage, focus) {
        this.form = form;
        this.fieldName = fieldName;
        this.errorMessage = errorMessage;
        this.focus = focus;
    },

    check : function() {
        var fieldValue = this.form[this.fieldName].value;
        if (fieldValue.indexOf("'") > -1 || fieldValue.indexOf("<") > -1
                || fieldValue.indexOf(">") > -1) {
            return false;
        }
        return true;
    }

});


var MaxLengthFieldChecker = Class.create(FieldChecker, {

    /**
     * Constructor for this class
     *
     * @param form
     *            target form instance
     * @param fieldName
     *            target field name
     * @param maxLength
     *            max length
     * @param errorMessage
     *            custom error message
     * @param focus
     *            whether or not field focusing
     */
    initialize : function(form, fieldName, maxLength, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
        this.maxLength = maxLength;
        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
        this.focus = focus;
    },

    /**
     * get max length
     */
    getMaxLength : function() {
        return this.maxLength;
    },

    /**
     * check max length
     */
    check : function() {
        return (this.form[this.fieldName].value.length <= this.maxLength);
    }

});


var MaxLengthByteFieldChecker = Class.create(FieldChecker, {

    /**
     * Constructor for this class
     *
     * @param form          target form instance
     * @param fieldName     target field name
     * @param maxLength     max byte length
     * @param errorMessage  custom error message
     * @param focus         whether or not field focusing
     */
    initialize : function(form, fieldName, maxLength, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
        this.maxLength = maxLength;
        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
        this.focus = focus;
    },

    /**
     * get max byte length
     */
    getMaxLength : function() {
        return this.maxLength;
    },

    /**
     * check max byte length
     */
    check : function() {
        str = this.form[this.fieldName].value;
        // UTF-8은 한글 1자가  3바이트이므로, 3으로 count하도록 수정.
        return ((str.length + ((escape(str) + "%u").match(/%u/g).length - 1) * 2) <= this.maxLength);
    }

});


var MinLengthFieldChecker = Class.create(FieldChecker, {

    /**
     * Constructor for this class
     *
     * @param form
     *            target form instance
     * @param fieldName
     *            target field name
     * @param minLength
     *            min length
     * @param errorMessage
     *            custom error message
     * @param focus
     *            whether or not field focusing
     */
    initialize : function(form, fieldName, minLength, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
        this.minLength = minLength;
        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
        this.focus = focus;
    },

    /**
     * get minimum length
     */
    getMinLength : function() {
        return this.minLength;
    },

    /**
     * check minimum length for target field value
     */
    check : function() {
        return (this.form[this.fieldName].value.length >= this.minLength);
    }

});


var MinLengthByteFieldChecker = Class.create(FieldChecker, {
    /**
     * Constructor for this class
     *
     * @param form          target form instance
     * @param fieldName     target field name
     * @param minLength     min byte length
     * @param errorMessage  custom error message
     * @param focus         whether or not focus on field
     */
    initialize : function(form, fieldName, minLength, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
        this.minLength = minLength;
        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
        this.focus = focus;
    },

    /**
     * get minimum byte length
     */
    getMinLength : function() {
        return this.minLength;
    },

    /**
     * check minimum byte length for target field value
     */
    check : function() {
        str = this.form[this.fieldName].value;
        return ((str.length + (escape(str) + "%u").match(/%u/g).length - 1) >= this.minLength);
    }

});


var RegexFieldChecker = Class.create(FieldChecker, {

    initialize : function(form, fieldName, regex, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
        this.regex = regex;
        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
        this.focus = focus;
    },

    getRegex: function() {
        return this.regex;
    },

    check : function() {
        var str = getCheckField(this).value;
        if (str.length == 0) {
            return true;
        }
        return ( str.search(this.regex) != -1 );
    }

});


var SelectionFieldChecker = Class.create(FieldChecker, {

    initialize: function(form, fieldName, firstIdx, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
        this.firstIdx = firstIdx;
        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
        this.focus = focus;
    },

    getFirstIndex: function() {
        return this.firstIdx;
    },

    check : function() {
        var selectedIndex = this.form[this.fieldName].selectedIndex;
        return ( selectedIndex >= this.firstIdx );
    }

});

var AtLeastOneCheckFieldChecker = Class.create(FieldChecker, {

    initialize: function(form, fieldName, errorMessage, focus, label) {
        this.form = form;
        this.fieldName = fieldName;
        this.errorMessage = getValidatorErrorMsg(errorMessage, label);

        if ( focus == true || focus == false ) {
            this.focus = focus;
        } else {
            this.focus = false;
            this.redirect = focus;
        }
    },

    check: function () {
        var ele = this.form[this.fieldName];
        if ( typeof(ele[0]) != "undefined" ) {
            for (var idxe = 0 ; idxe < ele.length ; idxe++) {
                if (ele[idxe].checked == true) {
                    return true;
                }
            }
            return false;
        } else {
            return ele.checked == true;
        }
    }

});

/**
 * form의 field 가져오기.
 */
function getCheckField(checker) {
    var formField = checker.form[checker.fieldName];
    if (formField && formField.length && formField.length > 1) {
        return formField[0];
    } else if (formField){
        return formField
    } else {
        return document.getElementById(checker.fieldName);
    }
}
