/**
 * @class Basic internationalization (i18n) service
 * @constructor
 * @param translations the catalog of translations to use
 * @param options options see the class attribute
 */
function I18N(translations, options) {
    this.initialize(translations, options);
}

I18N.prototype = {
    /** catalog of translations
     * @private
     */
    _translations: null,

    /** options of the decorator
     * <ul>
     * </ul>
     * @type Object
     */
    options: null,

    /** ctor
     * @private
     */
    initialize: function(translations, options) {
        this._translations = translations;
        this.options = Object.extend({}, options || {});
    },

    /**
     * search the translation of key into the catalog and substitute the params.
     * ex: key = "test", params = ["toto"] => if (catalog[key] == "%1") then toto
     * @param key the key to search for in the catalog
     * @param params the value to substitute in the string
     */
    translate: function(key, params) {
        params = params || [];
        var t = this._translations[key];
        //if the translation does not exist, use the key
        if (! t) {
//            t = '|' + key + '|';
            t = key;
        }

        //replace %1, %2, ... by the args
        for (var i = 0; i < params.length; i++) {
            //all %X not preceded by %
            var regexp = new RegExp("([^%]|^)%" + (i + 1), 'gi');
            t = t.replace(regexp, "$1" + params[i]);
        }

        return t;
    },

    /**
     * shortcut to {@link #translate}
     */
    _: function(key, params) {
        return this.translate(key, params);
    },

    /**
     * translate key and params and then lookup the string to see which part to take. <br/>
     * if the choice is not find, default to 'N/A'.<br/>
     * example key = "test", params = ["50"], choice = 1 =>
     * if (catalog[key] == "[0]no result[1]1 result[2,+inf]%1 results") then 50 results<br/>
     *
     * Restriction the return of translate(key, params) must not contain any [X,X] or
     * it will be considered as a possible set to lookup.
     *
     * @param key the key to search for in the catalog
     * @param params the value to substitute in the string
     * @param choice which part of the translation to take
     */
    translate_choice: function(key, params, choice) {
        //translate
        var t = this._(key, params);

        //find the sets: ex of matched : [-,0] [1] [2,+]
        var regexp = /\[[\d+|-](,[\d+|+])?\]/gi;
        var sets = t.match(regexp);

        //find in which set, the choice is
        var set = -1;
        for (var i = 0; i < sets.length; i++) {
            var curset = sets[i].substring(1, sets[i].length - 1).split(',');
            var min = (curset[0] == '-') ? Number.NEGATIVE_INFINITY : curset[0];
            var max = (curset[1] == '+') ? Number.POSITIVE_INFINITY : curset[1];
            if (! max) max = min; //case where [X]
            if (min <= choice && choice <= max) {
                set = i;
                break ;
            }
        }

        //not found => default value
        if (set == -1) {
            return 'N/A';
        }

        //substr the correct set
        var start = t.indexOf(sets[set]) + sets[set].length;
        var end = (set == sets.length - 1) ? t.length : t.indexOf(sets[set + 1]);
        return t.substring(start, end);
    },

    /**
     * shortcut to {@link #translate_choice}
     */
    _c: function(key, params, choice) {
        return this.translate_choice(key, params, choice);
    },

    /**
     * foramt a number according to the key translations['format_number']
     * @param number the number to format
     * @param dec_digits the number of digits after the decimal separator (default to 2)
     */
    format_number: function(number, dec_digits) {
        dec_digits = (dec_digits == undefined) ? 2 : dec_digits;
        number = number.toFixed(dec_digits);
        var format = this._translations['format_number'].split('|');
        var decimal_sep = format[0];
        var thousand_sep = format[1];

        //extract integer and decimal part of the number
        number += ''; //cast to string
        var int_part = number.split('.')[0];
        var dec_part = number.split('.')[1];

        //add thousand separator
        var int_part_by3 = /(\d+)(\d{3})/g;
        while (int_part_by3.test(int_part)) {
            int_part = int_part.replace(int_part_by3, '$1' + thousand_sep + '$2');
        }

        //add deciaml separator
        if (dec_part == undefined) {
            return int_part;
        }
        return int_part + decimal_sep + dec_part;
    },

    /**
     * shortcut to {@link #format_number}
     */
    _fn: function(number, dec_digits) {
        return this.format_number(number, dec_digits);
    },

    /**
     * foramt a currency according to the key translations['format_currency']
     * @param currency the number to format as a currency
     */
    format_currency: function(currency) {
        var format = this._translations['format_number'].split('|');
        var decimal_sep = format[0];
        var thousand_sep = format[1];

        var symbol = this._translations['format_currency'];

        var num = this.format_number(currency);
        //if there is no decimal, add decimal_separator + 00
        if (num.indexOf(decimal_sep) == -1) {
            num += decimal_sep + '00'
        }
        return num + ' ' + symbol;
    },

    /**
     * shortcut to {@link #format_currency}
     */
    _fc: function(number) {
        return this.format_currency(number);
    },

    /**
     * foramt a date according to the key translations['format_date']
     * @param date the date to format
     * @param format_suffix lookup for format_date + format_suffix (optional, default to '')
     */
    format_date: function(date, format_suffix) {
        format_suffix = format_suffix || '';
        var format = this._translations['format_date' + format_suffix];
        return DateFunction.formatDate(date, format);
    },

    /**
     * shortcut to {@link #format_date}
     */
    _fd: function(date, format_suffix) {
        return this.format_date(date, format_suffix);
    }
}
