/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

var g11n;

var globalization = {
    /**
    * Returns the string identifier for the client's current language.
    * It returns the language identifier string to the successCB callback with a
    * properties object as a parameter. If there is an error getting the language,
    * then the errorCB callback is invoked.
    *
    * @param {Function} successCB
    * @param {Function} errorCB
    *
    * @return Object.value {String}: The language identifier
    *
    * @error GlobalizationError.UNKNOWN_ERROR
    *
    * Example
    *    globalization.getPreferredLanguage(function (language) {alert('language:' + language.value + '\n');},
    *                                function () {});
    */
    getPreferredLanguage:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("getPreferredLanguage", args),
            data = JSON.parse(response);
        console.log("getPreferredLanguage: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                value: data.result
            });
        }
    },

    /**
    * Returns the string identifier for the client's current locale setting.
    * It returns the locale identifier string to the successCB callback with a
    * properties object as a parameter. If there is an error getting the locale,
    * then the errorCB callback is invoked.
    *
    * @param {Function} successCB
    * @param {Function} errorCB
    *
    * @return Object.value {String}: The locale identifier
    *
    * @error GlobalizationError.UNKNOWN_ERROR
    *
    * Example
    *    globalization.getLocaleName(function (locale) {alert('locale:' + locale.value + '\n');},
    *                                function () {});
    */
    getLocaleName:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("getLocaleName", args),
            data = JSON.parse(response);
        console.log("getLocaleName: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                value: data.result
            });
        }
    },


    /**
    * Returns a date formatted as a string according to the client's user preferences and
    * calendar using the time zone of the client. It returns the formatted date string to the
    * successCB callback with a properties object as a parameter. If there is an error
    * formatting the date, then the errorCB callback is invoked.
    *
    * The defaults are: formatLenght="short" and selector="date and time"
    *
    * @param {Date} date
    * @param {Function} successCB
    * @param {Function} errorCB
    * @param {Object} options {optional}
    *            formatLength {String}: 'short', 'medium', 'long', or 'full'
    *            selector {String}: 'date', 'time', or 'date and time'
    *
    * @return Object.value {String}: The localized date string
    *
    * @error GlobalizationError.FORMATTING_ERROR
    *
    * Example
    *    globalization.dateToString(new Date(),
    *                function (date) {alert('date:' + date.value + '\n');},
    *                function (errorCode) {alert(errorCode);},
    *                {formatLength:'short'});
    */
    dateToString:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("dateToString", args),
            data = JSON.parse(response);
        console.log("dateToString: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                value: data.result
            });
        }
    },


    /**
    * Parses a date formatted as a string according to the client's user
    * preferences and calendar using the time zone of the client and returns
    * the corresponding date object. It returns the date to the successCB
    * callback with a properties object as a parameter. If there is an error
    * parsing the date string, then the errorCB callback is invoked.
    *
    * The defaults are: formatLength="short" and selector="date and time"
    *
    * @param {String} dateString
    * @param {Function} successCB
    * @param {Function} errorCB
    * @param {Object} options {optional}
    *            formatLength {String}: 'short', 'medium', 'long', or 'full'
    *            selector {String}: 'date', 'time', or 'date and time'
    *
    * @return    Object.year {Number}: The four digit year
    *            Object.month {Number}: The month from (0 - 11)
    *            Object.day {Number}: The day from (1 - 31)
    *            Object.hour {Number}: The hour from (0 - 23)
    *            Object.minute {Number}: The minute from (0 - 59)
    *            Object.second {Number}: The second from (0 - 59)
    *            Object.millisecond {Number}: The milliseconds (from 0 - 999),
    *                                        not available on all platforms
    *
    * @error GlobalizationError.PARSING_ERROR
    *
    * Example
    *    globalization.stringToDate('4/11/2011',
    *                function (date) { alert('Month:' + date.month + '\n' +
    *                    'Day:' + date.day + '\n' +
    *                    'Year:' + date.year + '\n');},
    *                function (errorCode) {alert(errorCode);},
    *                {selector:'date'});
    */
    stringToDate:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("stringToDate", args),
            data = JSON.parse(response);
        console.log("stringToDate: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                year: data.result.year,
                month: data.result.month,
                day: data.result.day,
                hour: data.result.hour,
                minute: data.result.minute,
                second: data.result.second,
                millisecond: data.result.millisecond
            });
        }
    },


    /**
    * Returns a pattern string for formatting and parsing dates according to the client's
    * user preferences. It returns the pattern to the successCB callback with a
    * properties object as a parameter. If there is an error obtaining the pattern,
    * then the errorCB callback is invoked.
    *
    * The defaults are: formatLength="short" and selector="date and time"
    *
    * @param {Function} successCB
    * @param {Function} errorCB
    * @param {Object} options {optional}
    *            formatLength {String}: 'short', 'medium', 'long', or 'full'
    *            selector {String}: 'date', 'time', or 'date and time'
    *
    * @return    Object.pattern {String}: The date and time pattern for formatting and parsing dates.
    *                                    The patterns follow Unicode Technical Standard #35
    *                                    http://unicode.org/reports/tr35/tr35-4.html
    *            Object.timezone {String}: The abbreviated name of the time zone on the client
    *            Object.utc_offset {Number}: The current difference in seconds between the client's
    *                                        time zone and coordinated universal time.
    *            Object.dst_offset {Number}: The current daylight saving time offset in seconds
    *                                        between the client's non-daylight saving's time zone
    *                                        and the client's daylight saving's time zone.
    *
    * @error GlobalizationError.PATTERN_ERROR
    *
    * Example
    *    globalization.getDatePattern(
    *                function (date) {alert('pattern:' + date.pattern + '\n');},
    *                function () {},
    *                {formatLength:'short'});
    */
    getDatePattern:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("getDatePattern", args),
            data = JSON.parse(response);
        console.log("getDatePattern: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                pattern: data.result.pattern,
                timezone: data.result.timezone,
                utc_offset: data.result.utc_offset,
                dst_offset: data.result.dst_offset
            });
        }
    },


    /**
    * Returns an array of either the names of the months or days of the week
    * according to the client's user preferences and calendar. It returns the array of names to the
    * successCB callback with a properties object as a parameter. If there is an error obtaining the
    * names, then the errorCB callback is invoked.
    *
    * The defaults are: type="wide" and item="months"
    *
    * @param {Function} successCB
    * @param {Function} errorCB
    * @param {Object} options {optional}
    *            type {String}: 'narrow' or 'wide'
    *            item {String}: 'months', or 'days'
    *
    * @return Object.value {Array{String}}: The array of names starting from either
    *                                        the first month in the year or the
    *                                        first day of the week.
    * @error GlobalizationError.UNKNOWN_ERROR
    *
    * Example
    *    globalization.getDateNames(function (names) {
    *        for(var i = 0; i < names.value.length; i++) {
    *            alert('Month:' + names.value[i] + '\n');}},
    *        function () {});
    */
    getDateNames:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("getDateNames", args),
            data = JSON.parse(response);
        console.log("getDateNames: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                value: data.result
            });
        }
    },

    /**
    * Returns whether daylight savings time is in effect for a given date using the client's
    * time zone and calendar. It returns whether or not daylight savings time is in effect
    * to the successCB callback with a properties object as a parameter. If there is an error
    * reading the date, then the errorCB callback is invoked.
    *
    * @param {Date} date
    * @param {Function} successCB
    * @param {Function} errorCB
    *
    * @return Object.dst {Boolean}: The value "true" indicates that daylight savings time is
    *                                in effect for the given date and "false" indicate that it is not.
    *
    * @error GlobalizationError.UNKNOWN_ERROR
    *
    * Example
    *    globalization.isDayLightSavingsTime(new Date(),
    *                function (date) {alert('dst:' + date.dst + '\n');}
    *                function () {});
    */
    isDayLightSavingsTime:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("isDayLightSavingsTime", args),
            data = JSON.parse(response);
        console.log("isDayLightSavingsTime: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                dst: data.result
            });
        }
    },

    /**
    * Returns the first day of the week according to the client's user preferences and calendar.
    * The days of the week are numbered starting from 1 where 1 is considered to be Sunday.
    * It returns the day to the successCB callback with a properties object as a parameter.
    * If there is an error obtaining the pattern, then the errorCB callback is invoked.
    *
    * @param {Function} successCB
    * @param {Function} errorCB
    *
    * @return Object.value {Number}: The number of the first day of the week.
    *
    * @error GlobalizationError.UNKNOWN_ERROR
    *
    * Example
    *    globalization.getFirstDayOfWeek(function (day)
    *                { alert('Day:' + day.value + '\n');},
    *                function () {});
    */
    getFirstDayOfWeek:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("getFirstDayOfWeek", args),
            data = JSON.parse(response);
        console.log("getFirstDayOfWeek: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                value: data.result
            });
        }
    },


    /**
    * Returns a number formatted as a string according to the client's user preferences.
    * It returns the formatted number string to the successCB callback with a properties object as a
    * parameter. If there is an error formatting the number, then the errorCB callback is invoked.
    *
    * The defaults are: type="decimal"
    *
    * @param {Number} number
    * @param {Function} successCB
    * @param {Function} errorCB
    * @param {Object} options {optional}
    *            type {String}: 'decimal', "percent", or 'currency'
    *
    * @return Object.value {String}: The formatted number string.
    *
    * @error GlobalizationError.FORMATTING_ERROR
    *
    * Example
    *    globalization.numberToString(3.25,
    *                function (number) {alert('number:' + number.value + '\n');},
    *                function () {},
    *                {type:'decimal'});
    */
    numberToString:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("numberToString", args),
            data = JSON.parse(response);
        console.log("numberToString: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                value: data.result
            });
        }
    },

    /**
    * Parses a number formatted as a string according to the client's user preferences and
    * returns the corresponding number. It returns the number to the successCB callback with a
    * properties object as a parameter. If there is an error parsing the number string, then
    * the errorCB callback is invoked.
    *
    * The defaults are: type="decimal"
    *
    * @param {String} numberString
    * @param {Function} successCB
    * @param {Function} errorCB
    * @param {Object} options {optional}
    *            type {String}: 'decimal', "percent", or 'currency'
    *
    * @return Object.value {Number}: The parsed number.
    *
    * @error GlobalizationError.PARSING_ERROR
    *
    * Example
    *    globalization.stringToNumber('1234.56',
    *                function (number) {alert('Number:' + number.value + '\n');},
    *                function () { alert('Error parsing number');});
    */
    stringToNumber:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("stringToNumber", args),
            data = JSON.parse(response);
        console.log("stringToNumber: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                value: data.result
            });
        }
    },

    /**
    * Returns a pattern string for formatting and parsing numbers according to the client's user
    * preferences. It returns the pattern to the successCB callback with a properties object as a
    * parameter. If there is an error obtaining the pattern, then the errorCB callback is invoked.
    *
    * The defaults are: type="decimal"
    *
    * @param {Function} successCB
    * @param {Function} errorCB
    * @param {Object} options {optional}
    *            type {String}: 'decimal', "percent", or 'currency'
    *
    * @return    Object.pattern {String}: The number pattern for formatting and parsing numbers.
    *                                    The patterns follow Unicode Technical Standard #35.
    *                                    http://unicode.org/reports/tr35/tr35-4.html
    *            Object.symbol {String}: The symbol to be used when formatting and parsing
    *                                    e.g., percent or currency symbol.
    *            Object.fraction {Number}: The number of fractional digits to use when parsing and
    *                                    formatting numbers.
    *            Object.rounding {Number}: The rounding increment to use when parsing and formatting.
    *            Object.positive {String}: The symbol to use for positive numbers when parsing and formatting.
    *            Object.negative: {String}: The symbol to use for negative numbers when parsing and formatting.
    *            Object.decimal: {String}: The decimal symbol to use for parsing and formatting.
    *            Object.grouping: {String}: The grouping symbol to use for parsing and formatting.
    *
    * @error GlobalizationError.PATTERN_ERROR
    *
    * Example
    *    globalization.getNumberPattern(
    *                function (pattern) {alert('Pattern:' + pattern.pattern + '\n');},
    *                function () {});
    */
    getNumberPattern:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("getNumberPattern", args),
            data = JSON.parse(response);
        console.log("getNumberPattern: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                pattern: data.result.pattern,
                symbol: data.result.symbol,
                fraction: data.result.fraction,
                rounding: data.result.rounding,
                positive: data.result.positive,
                negative: data.result.negative,
                decimal: data.result.decimal,
                grouping: data.result.grouping
            });
        }
    },

    /**
    * Returns a pattern string for formatting and parsing currency values according to the client's
    * user preferences and ISO 4217 currency code. It returns the pattern to the successCB callback with a
    * properties object as a parameter. If there is an error obtaining the pattern, then the errorCB
    * callback is invoked.
    *
    * @param {String} currencyCode
    * @param {Function} successCB
    * @param {Function} errorCB
    *
    * @return    Object.pattern {String}: The currency pattern for formatting and parsing currency values.
    *                                    The patterns follow Unicode Technical Standard #35
    *                                    http://unicode.org/reports/tr35/tr35-4.html
    *            Object.code {String}: The ISO 4217 currency code for the pattern.
    *            Object.fraction {Number}: The number of fractional digits to use when parsing and
    *                                    formatting currency.
    *            Object.rounding {Number}: The rounding increment to use when parsing and formatting.
    *            Object.decimal: {String}: The decimal symbol to use for parsing and formatting.
    *            Object.grouping: {String}: The grouping symbol to use for parsing and formatting.
    *
    * @error GlobalizationError.FORMATTING_ERROR
    *
    * Example
    *    globalization.getCurrencyPattern('EUR',
    *                function (currency) {alert('Pattern:' + currency.pattern + '\n');}
    *                function () {});
    */
    getCurrencyPattern:function(successCB, failureCB, args, env) {
        var result = new PluginResult(args, env),
            response = g11n.getInstance().InvokeMethod("getCurrencyPattern", args),
            data = JSON.parse(response);
        console.log("getCurrencyPattern: " + JSON.stringify(response));

        if (data.error !== undefined) {
            result.error({
                code: data.error.code,
                message: data.error.message
            });
        } else {
            result.ok({
                pattern: data.result.pattern,
                code: data.result.code,
                fraction: data.result.fraction,
                rounding: data.result.rounding,
                decimal: data.result.decimal,
                grouping: data.result.grouping
            });
        }
    }
};

module.exports = globalization;

function lineArgsFromArray(args) {
    var cmd = "";

    if ("callbackId" in args)
        cmd += decodeURIComponent(args.callbackId);
    if ("0" in args) {
        if (cmd.length > 0)
            cmd += " ";
        cmd += decodeURIComponent(args["0"]);
    }

    return cmd;
}

function cmdLineForMethod(method, args) {
    var cmd = lineArgsFromArray(args);
    if (cmd.length > 0)
        return method + " " + cmd;
    else
        return method;
}

///////////////////////////////////////////////////////////////////
// JavaScript wrapper for JNEXT plugin
///////////////////////////////////////////////////////////////////

JNEXT.Globalization = function () {
    var self = this,
        hasInstance = false;

    self.InvokeMethod = function (method, args) {
        //This is how Javascript calls into native
        return JNEXT.invoke(self.m_id, cmdLineForMethod(method, args));
    };

    self.init = function () {
        //Checks that the jnext library is present and loads it
        if (!JNEXT.require("libGlobalization")) {
            return false;
        }

        //Creates the native object that this interface will call
        self.m_id = JNEXT.createObject("libGlobalization.Globalization");

        if (self.m_id === "") {
            return false;
        }

        //Registers for the JNEXT event loop
        JNEXT.registerEvents(self);
    };

    self.m_id = "";

    //Used by JNEXT library to get the ID
    self.getId = function () {
        return self.m_id;
    };

    //Not truly required but useful for instance management
    self.getInstance = function () {
        if (!hasInstance) {
            self.init();
            hasInstance = true;
        }
        return self;
    };
};

g11n = new JNEXT.Globalization();

