/**
 * Checks if obj is an array ([]) or Array()
 *
 * @param Object
 * @return TRUE is it's an array object, otherwise FALSE
 */
function isArray(obj) {
    if (obj.constructor.toString().indexOf("Array") == -1)
        return false;
    else
        return true;
}

/**
 * Minimal implemenation of sprintf.
 * Currently interprets integers, floats, strings and characters by ascii code.
 * Interpretation of integers is done with parseInt() so you can use e.g. "0x..."
 *
 * @param String that contains sprintf pattern
 * @param[] Optional and variable number of replacement arguments. 
 *   If the first of these arguments is an array, it will be used as replacement arguments
 *   and the rest of arguments passed to the function will be ignored.
 */
function sprintf(str) {
    if (str == null || str.length == 0)
        return str;
    var args = arguments;
    if (isArray(arguments[1])) {
        args = arguments[1];
    }
    var parts = str.split('%');
    var out = parts[0];
    var re = /^([sdfc])(.*)$/;
    var indexAdj = 0;
    for (var i = 1; i < parts.length; i++) {
        matches = re.exec(parts[i]);
        a = i - indexAdj;
        if (!matches || args[a] == null) {
            indexAdj++;
            out += "%" + parts[i];
            continue;
        }
        if (matches[1] == 'd') out += parseInt(args[a]);
        else if (matches[1] == 'f') out += parseFloat(args[a]);
        else if (matches[1] == 's') out += args[a];
        else if (matches[1] == 'c') out += String.fromCharCode(parseInt(args[a]));
        out += matches[2];
    }
    return out;
}

/**
 * Localization function in the spirit of gettext.
 * This function expects to find localization strings in an object called 'i18n'.
 * If that object doesn't exist or doesn't have a variable named by 'str' parameter,
 * it will return un-altered 'str'.
 *
 * @param String localization string
 * @param[] Replacement parameters - these are passed to sprintf as a single array.
 */
function _(str) {
    if (typeof(i18n) != "undefined" && i18n[str]) {
        return sprintf(i18n[str], Array.prototype.slice.call(arguments));
    } else {
        return sprintf(str, Array.prototype.slice.call(arguments));
    }
}
