// *********************
// Exception definitions
// *********************
function Exception() {
    this.message = new String();
    this.errorID = null;
}
Exception.prototype.getMessage = function() {
    return this.message;
}
Exception.prototype.getErrorID = function() {
    return this.errorID;
}

// Required Exception
function RequiredException() {
    this.message = "Field Required!";
    this.errorID = 1;
}
RequiredException.prototype = new Exception();
RequiredException.constructor = RequiredException;
// Required Exception end

// Syntax Exception
function SyntaxException() {
    this.message = "Syntax Error!";
    this.errorID = 2;
}
SyntaxException.prototype = new Exception();
SyntaxException.constructor = SyntaxException;
// Syntax Exception end
// *************************
// Exception definitions end
// *************************









// **********************
// DataObject definitions
// **********************
// Abstract data class
function DataObject() {
}
DataObject.prototype.toString = function() {
    var text = new String();
    
    for (var i in this) {
        var value = new String(this[i]);
        value = (value.length > 30)? "..." : value;
        
        text += "object." + i + " = " + value + "\n";
    }
    
    return text;
}
// Abstract data class end

// DataObjectMail class
function DataObjectMail(value, required) {
    this.value = value;
    this.required = required;
}
DataObjectMail.prototype = new DataObject();
DataObjectMail.constructor = DataObjectMail;
// DataObjectMail class end

// DataObjectString class
function DataObjectString(value, minLength, required) {
    this.value = value;
    this.minLength = minLength;
    this.required = required;
}
DataObjectString.prototype = new DataObject();
DataObjectString.constructor = DataObjectString;
// DataObjectString class end

// DataObjectSelect class
function DataObjectSelect(selectedIndex, nonzero, required) {
    this.selectedIndex = selectedIndex;
    this.nonzero = nonzero;
    this.required = required;
}
DataObjectSelect.prototype = new DataObject();
DataObjectSelect.constructor = DataObjectSelect;
// DataObjectSelect class end
// **************************
// DataObject definitions end
// **************************











// **********************
// Validation definitions
// **********************
// Abstract base Validate class
function Validate() {
}
Validate.prototype._checkRequired = function() {
}
Validate.prototype._checkSyntax = function() {
}
Validate.prototype.check = function() {
    var requiredOK = this._checkRequired();
    if (requiredOK && this.required) {
        var syntaxOK = this._checkSyntax();
        if (syntaxOK) {
            return true;
        } else {
            throw new SyntaxException();
        }
    } else if (requiredOK && !this.required) {
        return true;
    } else {
        throw new RequiredException();
    }
}
// Abstract base Validate class end

// Validate Mail class
function ValidateMail(DataObjectMail) {
    this.value = DataObjectMail.value;
    this.required = DataObjectMail.required;
}
ValidateMail.prototype = new Validate();
ValidateMail.constructor = ValidateMail;
ValidateMail.prototype._checkRequired = function() {
    if (this.required) {
        var value = new String(this.value);
        var valueLen = value.length;
        if (valueLen == 0) {
            return false;
        } else {
            return true;
        }
    } else {
        return true;
    }
}
ValidateMail.prototype._checkSyntax = function() {
    var value = this.value;
	var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	
	if (filter.test(value)) {
	    return true;
	} else {
	    return false;
	}
}
// Validate Mail class end

// Validate String class
function ValidateString(DataObjectString) {
    this.value = DataObjectString.value;
    this.minLength = DataObjectString.minLength;
    this.required = DataObjectString.required;
}
ValidateString.prototype = new Validate();
ValidateString.constructor = ValidateString;
ValidateString.prototype._checkRequired = function() {
    if (this.required) {
        var value = new String(this.value);
        var valueLen = value.length;
        if (valueLen == 0) {
            return false;
        } else {
            return true;
        }
    } else {
        return true;
    }
}
ValidateString.prototype._checkSyntax = function() {
    var value = new String(this.value);
    var valueLen = value.length;
    
    if (valueLen < this.minLength) {
        return false;
    } else {
        return true;
    }
}
// Validate String class end

// Validate Select class
function ValidateSelect(DataObjectSelect) {
    this.selectedIndex = DataObjectSelect.selectedIndex;
    this.nonzero = DataObjectSelect.nonzero;
    this.required = DataObjectSelect.required;
}
ValidateSelect.prototype = new Validate();
ValidateSelect.constructor = ValidateSelect;
ValidateSelect.prototype._checkRequired = function() {
    if (this.required) {
        if (!this.nonzero) {
            if (this.selectedIndex > 0) {
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    } else {
        return true;
    }
}
ValidateSelect.prototype._checkSyntax = function() {
    return true;
}
// Validate Select class end
// **************************
// Validation definitions end
// **************************










// ********
// EXAMPLES
// ********
/*
var TestObj = new DataObjectMail("test@test.com", true);
alert(TestObj);
var test = new ValidateMail(TestObj);
try {
    alert(test.check());
} catch(e) {
    alert(e.getMessage());
}
*/

/*
var TestObj = new DataObjectString("as34", 4, true);
alert(TestObj);
var test = new ValidateString(TestObj);
try {
    alert(test.check());
} catch(e) {
    alert(e.getMessage());
}
*/

/*
var TestObj = new DataObjectSelect(0, false, true);
alert(TestObj);
var test = new ValidateSelect(TestObj);
try {
    alert(test.check());
} catch(e) {
    alert(e.getMessage());
}
*/
// ************
// EXAMPLES END
// ************


// **********************
// EXAMPLE ERROR MESSAGES
// **********************
/*
var ERROR_REQUIRED_MESSAGES = {
    type: "Field TYPE is required! Please fill it in!",
    size: "Field SIZE is required! Please fill it in!",
    figures: "Field FIGURES is required! Please fill it in!",
    figure1: "Field FIGURE1 is required! Please fill it in!",
    figure2: "Field FIGURE2 is required! Please fill it in!",
    figure3: "Field FIGURE3 is required! Please fill it in!",
    figure4: "Field FIGURE4 is required! Please fill it in!",
    figure5: "Field FIGURE5 is required! Please fill it in!",
    background: "Field BACKGROUND is required! Please fill it in!",
    name: "Field NAME is required! Please fill it in!",
    email: "Field E-MAIL is required! Please fill it in!"
};
var ERROR_SYNTAX_MESSAGES = {
    name: "Field NAME is too short! Please fill it in minimum 3 symbols!",
    email: "Field E-MAIL is not valid! Please fill it in correctly!"
};
var ERROR_MESSAGES = [
    {},
    ERROR_REQUIRED_MESSAGES,
    ERROR_SYNTAX_MESSAGES
];
*/
// **************************
// EXAMPLE ERROR MESSAGES END
// **************************

// ****************************
// EXAMPLE INIT FIELD STRUCTURE
// ****************************
/*
var fieldIDsList = [
    {id: "type", type: "select", required: true},
    {id: "size", type: "select", required: true},
    {id: "figures", type: "select", required: true},
    {id: "figure1", type: "select", required: true},
    {id: "figure2", type: "select", required: true},
    {id: "figure3", type: "select", required: true},
    {id: "figure4", type: "select", required: true},
    {id: "figure5", type: "select", required: true},
    {id: "background", type: "select", required: true},
    {id: "name", type: "string", required: true},
    {id: "email", type: "mail", required: true},
    {id: "howdid", type: "string", required: true},
    {id: "phone", type: "string", required: true},
    {id: "instructions", type: "string", required: true}
];
*/
// ********************************
// EXAMPLE INIT FIELD STRUCTURE END
// ********************************

var fieldObjectList = [];

function initFields() {
    fieldObjectList = [];
    for (var i in fieldIDsList) {
        var obj = fieldIDsList[i];
        var HTMLObj = document.getElementById(obj.id);
        //alert(HTMLObj + " :: " + obj.id)
        var required = obj.required;
        
        if (obj.type == "select") {
            fieldObjectList[i] = new DataObjectSelect(HTMLObj.selectedIndex, false, required);
        } else if (obj.type == "string") {
            fieldObjectList[i] = new DataObjectString(HTMLObj.value, 3, required);
        } else if (obj.type == "mail") {
            fieldObjectList[i] = new DataObjectMail(HTMLObj.value, required);
        }
    }
}

function onSubmit() {
    initFields();
    
    for (var i in fieldObjectList) {
        var obj = fieldObjectList[i];
        try {
            switch (fieldIDsList[i].type) {
                case "string":
                    var validationObj = new ValidateString(obj);
                    break;
                case "mail":
                    var validationObj = new ValidateMail(obj);
                    break;
                case "select":
                    var validationObj = new ValidateSelect(obj);
            }
            validationObj.check();
        } catch(e) {
            alert(ERROR_MESSAGES[e.getErrorID()][fieldIDsList[i].id]);
            //alert("Filed \"" + fieldIDsList[i].id + "\" has the following problem: " + e.getMessage());
            document.getElementById(fieldIDsList[i].id).focus();
            return false;
        }
    }
    
    return true;
}
