function zeroPrefix(value, size)
{
	var string = value + "";
	while (string.length < size)
	{
		string = "0" + string;
	}
	return string;
}

Date.prototype.toDbFormat = function()
{
	return this.getFullYear() + "-" + zeroPrefix(this.getMonth(), 2) + "-" + zeroPrefix(this.getDate(), 2);
};


function getFileRef(filename)
{
    return filename.substring(filename.lastIndexOf("_") + 1);
}

var formData = {
};

function addFieldHandling(field, validation, reset)
{
    var fieldId = field.parents("form:first").attr("id");
    var form = getRegisteredForm(fieldId);
    form.validationFunctions.push(validation);
    form.resetFieldFunctions.push(reset);
}

function validateAllFields(form)
{
    var data = formData[form];
    if (data == null) return true;
    var array = data.validationFunctions;
    var ok = true;
    for (var i = 0; i < array.length; i++)
    {
        if (!array[i]()) ok = false;
    }
    $("#submitResult").hide();
    return ok;
}

function resetAllFields(form)
{
    var data = formData[form];
    if (data == null) return;
    var array = data.resetFieldFunctions;
    for (var i = 0; i < array.length; i++)
    {
        array[i]();
    }
}

function handleDefaultFormSubmit(data, status, fun)
{
    if (fun)
    {
        if (fun(data)) return;
    }
    $("#submitResult").show();
    if (status != "success")
    {
        alert("status was " + status + " " + data);
        data = { success:false, error: "noconnect", message: "Connection Failed" };
    }
    if (data.success)
    {
        $("#submitResult").removeClass("formError").addClass("formSuccess").html(data.message);
    }
    else
    {
        $("#submitResult").removeClass("formSuccess")
            .addClass("formError").html(data.message);
    }
}

function hideSubmit(form)
{
    $('#' + form + ' input[type=submit]', this).attr('disabled', 'disabled');
}

function showSubmit(form)
{
    $('#' + form + ' input[type=submit]', this).attr('disabled', 'enabled');
}

function registerForm(form, url, fun)
{
    formData[form] = { validationFunctions : [], resetFieldFunctions: [] };
    $(function() { $('#' + form).ajaxForm({
        dataType: 'json',
        url: url,
        iframe: true,
        type: "POST",
        beforeSubmit: function() { if (!validateAllFields(form)) return false; hideSubmit(form); return true; },
        success: function(data, status) { showSubmit(form); handleDefaultFormSubmit(data, status, fun); }
    }); });
}

function getRegisteredForm(form)
{
    return formData[form];
}

function addValidationToField(id, type, min, max)
{
    var validationFunction = eval("validate" + type + "Field");
    var field = $("#" + id);
    var f_running = function()
    {
        return validationFunction(true, id, min, max);
    };
    var f_submit = function()
    {
        return validationFunction(false, id, min, max);
    };
    field.focus(function()
    {
        getErrorMessageElement(id).hide();
        field.removeClass("validationError");
    }).blur(f_submit).keyup(f_running);
    addFieldHandling(field, f_submit, function()
    {
        field.removeClass("validationError");
        getOkMarkerElement(id).hide();
        getErrorMarkerElement(id).hide();
        getErrorMessageElement(id).hide();
        field.val("");
    });
}

function getOkMarkerElement(id)
{
    return $("#" + id + "FieldOkMarker");
}

function getErrorMarkerElement(id)
{
    return $("#" + id + "FieldErrorMarker");
}
function getErrorMessageElement(id)
{
    return $("#" + id + "FieldErrorMessage");
}

function validateField(running, id, required, val_function)
{
    var field = $("#" + id);
    var value = field.val();
    if (!running)
    {
        getErrorMessageElement(id).hide();
        field.removeClass("validationError");
    }
    var errorMarker = getErrorMarkerElement(id).hide();
    var okMarker = getOkMarkerElement(id).hide();
    var result;
    if (value == "" || value == null)
    {
        if (!required) return true;
        result = false;
    }
    else
    {
        result = val_function(value);
    }
    if (!result)
    {
        if (!running)
        {
            getErrorMessageElement(id).show();
            field.addClass("validationError");
        }

        errorMarker.show();
        return false;
    }
    okMarker.show();
    return true;
}

function validatePasswordField(running, id, min, max)
{
    validatePasswordVerifyField(running, id + "Verify", min, 255);
    return validateStringField(running, id, 8 * min, 255);
}

function validatePhoneField(running, id, min, max)
{
    return validateField(running, id, min > 0, function(val)
    {
        var phone_pattern = /^(\+[0-9]{1,3})?([-\. ]*((\([0-9]+\))|([0-9]+)))+$/;
        return phone_pattern.test(val);
    });
}

function validateEmailField(running, id, min, max)
{
    return validateField(running, id, min > 0, function(val)
    {
        var email_pattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
        return email_pattern.test(val);
    });
}
function validatePasswordVerifyField(running, id, min, max)
{
    var password = $("#" + id.replace("Verify", "")).val();
    return validateField(running, id, password.length > 0, function(val)
    {
        return val == password;
    });
}
function validateStringField(running, id, min, max)
{
    return validateField(running, id, min > 0, function(val)
    {
        return val.length >= min && (max < 1 || val.length <= max);
    });
}

function validateIntegerField(running, id, min, maxsize)
{
    return validateField(running, id, min > 0, function(val)
    {
        var integerPattern = /^[\-]?[0-9]+$/;
        return val.length <= maxsize && integerPattern.test(val) && !isNaN(parseInt(val));
    });
}

function validateLongField(running, id, min, maxsize)
{
    return validateIntegerField(running, id, min, maxsize);
}

function validateFloatField(running, id, min, maxsize)
{
    return validateField(running, id, min > 0, function(val)
    {
        val = val.replace(",", ".");
        var floatPattern = /^[\-]?[0-9]+(\.[0-9]+)?$/;
        return val.length <= maxsize && floatPattern.test(val) && !isNaN(parseFloat(val));
    });
}

function validateDateField(running, id, min, max)
{
    return validateField(running, id, min > 0, function(val)
    {
        return Date.fromISOformat(val) != null;
    });
}

Date.fromISOformat = function(string)
{
    if (string == null) return null;
    var datePattern = /^([1-9][0-9]{3})-([01]?[0-9])-([0-3]?[0-9])([ ]([0-2]?[0-9])\:([0-5]?[0-9])(:([0-5]?[0-9])(\.([0-9]{1,3}))?)?)?$/;
    var result = datePattern.exec(string);
    if (result == null) return null;
    var year = parseInt(result[1]);
    var month = parseInt(result[2]);
    var day = parseInt(result[3]);
    var hour = parseInt(result[5]);
    var minute = parseInt(result[6]);
    var second = parseInt(result[8]);
    var milli = parseInt(result[10]);
    if (isNaN(hour))
    {
        hour = 0;
        minute = 0;
        second = 0;
        milli = 0;
    }
    if (isNaN(second))
    {
        second = 0;
        milli = 0;
    }
    if (isNaN(milli))
    {
        milli = 0;
    }
    if (month > 12 || month < 1
            || day > 31 || day < 1
            || hour > 23 || hour < 0
            || minute > 59 || minute < 0
            || second > 59 || second < 0
            || milli > 999 || milli < 0) return null;
    return new Date(year, month - 1, day, hour, minute, second, milli);
};

Date.fromDbFormat = function(string)
{
	if (string == null) return null;
	var parts = string.split("-");
	if (parts.length != 3) return null;
	return new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));
};

Date.prototype.plusMonths = function(months)
{
	var month = this.getMonth() + months;
	var year = this.getFullYear();
	while (month > 11)
	{
		month -= 11;
		year++;
	}
	return new Date(year, month, this.getDate());
};

Array.prototype.indexOf = function(obj)
{
    var len = this.length;
    for (var i = 0; i < len; i++)
    {
        if (this[i] == obj) return i;
    }
    return -1;
};

Array.prototype.contains = function(obj)
{
    return this.indexOf(obj) > -1;
};

Array.prototype.remove = function(obj)
{
    var index = this.indexOf(obj);
    if (index > -1)
    {
        this.splice(index, 1);
        return obj;
    }
    return null;
};

function getRadioButtonValue(radioButtonArray)
{
	for (var i = 0; i < radioButtonArray.length; i++)
	{
		if (radioButtonArray[i].checked)
		{
			return radioButtonArray[i].value;
		}
	}
	return null;
}

function addHover(element)
{
    return element.hover(function() { $(this).addClass("hover"); }, function() { $(this).removeClass("hover"); });
}

function redirect(url)
{
    document.location = url;
    return false;
}
function elementAsJSON(element)
{
	return '"' + element + '":' + JSON.stringify(document.getElementById(element).value);
}

// Helper function to construct a data tree for updates.
function addTreeData(parentElement, data)
{
    var parentId = parentElement.attributes.id.replace(/.*_/, "");
    data[parentId] = parentElement.data.title;
    var result = "";
    if (parentElement.children)
    {
        var child;
        for (var i = 0; i < parentElement.children.length; i++)
        {
            child = parentElement.children[i];
            result += child.attributes.id.replace(/.*_/, "") + "+" + i + "+" + parentId + "|";
            result += addTreeData(child, data);
        }
    }
    return result;
}

// Saves the update using ajax.
function saveTreeData(treeElement, page, returnFunction)
{
    // Get the tree
    var tree = jQuery.tree.reference("#" + treeElement);
    // Get all data as JSON
    var jsonData = tree.get(null, "json");
    // Construct a update string on the format
    // "id+sortOrder+parentId|id+sortOrder+parentId|id+sortOrder+parentId"
    var output = "";
    var data = {};
    var id;
    if (jsonData.attributes)
    {
        id = jsonData.attributes.id.replace(/.*_/, "");
        output += id + "+0+0|";
        output += addTreeData(jsonData, data);
    }
    else
    {
        for (var i = 0; i < jsonData.length; i++)
        {
            id = jsonData[i].attributes.id.replace(/.*_/, "");
            output += id + "+" + i + "+0|";
            output += addTreeData(jsonData[i], data);
        }
    }
    data["treeUpdate"] = output;
    $.post(page, data, returnFunction);
}

function enableRenameTree(treeId)
{
    $("#" + treeId + " ul > li").dblclick(function()
    {
        $.tree.focused().rename();
        return true;
    });
}
