/*
THIS INFRAGISTICS ULTIMATE SOFTWARE LICENSE  AGREEMENT ("AGREEMENT") LOCATED HERE:
https://www.infragistics.com/legal/license/igultimate-la
https://www.infragistics.com/legal/license/igultimate-eula
GOVERNS THE LICENSING, INSTALLATION AND USE OF INFRAGISTICS SOFTWARE. BY DOWNLOADING AND/OR INSTALLING AND USING INFRAGISTICS SOFTWARE:  you are indicating that you have read and understand this Agreement, and agree to be legally bound by it on behalf of the yourself and your company.
*/
import { CultureInfo } from "./culture";
import { FormatException } from "./type";
export function ieeeRemainder(a, b) {
    var r = Math.abs(a % b);
    if (isNaN(r) || r == b || r <= Math.abs(b) / 2.0) {
        return r;
    }
    else {
        return Math.sign(a) * (r - b);
    }
}
;
export function numberToString1(value, provider) {
    return value.toLocaleString(provider.name, { useGrouping: false }); // TODO: Figure out how to use the provider correctly here
}
export function tryParseNumber1(s, style, provider) {
    var value, i, currentCharCode;
    provider = provider || CultureInfo.currentCulture;
    /*jslint bitwise: true */
    if ((style & 1 /* AllowLeadingWhite */) === 0) {
        var index = 0;
        while (index < s.length && s[index] === ' ') {
            index++;
        }
        s = s.substring(index);
    }
    if ((style & 2 /* AllowTrailingWhite */) === 0) {
        var index = s.length - 1;
        while (index >= 0 && s[index] === ' ') {
            index--;
        }
        s = s.substring(0, index + 1);
    }
    if (s.length != s.trim().length) {
        return {
            p3: 0,
            ret: false
        };
    }
    var numberFormat = provider.numberFormat;
    if (style & 256 /* AllowCurrencySymbol */) {
        // TODO: Use the locale specific symbol from the provider here
        if (s[0] == "$") {
            s = s.slice(1);
        }
    }
    var multiplier = 1;
    var hadParentheses = false;
    if (style & 16 /* AllowParentheses */) {
        if (s[0] == "(" && s[s.length - 1] == ")") {
            hadParentheses = true;
            multiplier *= -1;
            s = s.slice(1, -1);
        }
    }
    if (style & 256 /* AllowCurrencySymbol */) {
        // TODO: Use the locale specific symbol from the provider here
        if (s[0] == "$") {
            s = s.slice(1);
        }
    }
    if (style & 4 /* AllowLeadingSign */) {
        var positiveSign = numberFormat.positiveSign;
        var negativeSign = numberFormat.negativeSign;
        if (s[0] == positiveSign || s[0] == negativeSign) {
            if (hadParentheses) {
                return {
                    p3: 0,
                    ret: false
                };
            }
            if (s[0] == negativeSign) {
                multiplier *= -1;
            }
            s = s.slice(1);
        }
    }
    if (style & 8 /* AllowTrailingSign */) {
        // TODO
    }
    if (style & 32 /* AllowDecimalPoint */) {
        if (style & 128 /* AllowExponent */) {
            // TODO
        }
        if (style & 64 /* AllowThousands */) {
            var decimalSeparator = numberFormat.numberDecimalSeparator;
            var groupSeparator = numberFormat.numberGroupSeparator;
            var hitDecimalSeparator = false;
            for (i = 0; i < s.length; i++) {
                switch (s[i]) {
                    case groupSeparator:
                        if (hitDecimalSeparator) {
                            return {
                                p3: 0,
                                ret: false
                            };
                        }
                        s = s.slice(0, i) + s.slice(i + 1);
                        i--;
                        break;
                    case decimalSeparator:
                        hitDecimalSeparator = true;
                        if (decimalSeparator != ".") {
                            s = s.slice(0, i) + "." + s.slice(i + 1);
                        }
                        break;
                }
            }
        }
        value = Number(s);
        if (value !== null && isFinite(value) && s.trim().length !== 0) {
            return {
                p3: value * multiplier,
                ret: true
            };
        }
    }
    else {
        var zeroCharCode = "0".charCodeAt(0);
        var nineCharCode = "9".charCodeAt(0);
        value = 0;
        if (style & 512 /* AllowHexSpecifier */) {
            var aCharCode = "a".charCodeAt(0);
            var fCharCode = "f".charCodeAt(0);
            var ACharCode = "A".charCodeAt(0);
            var FCharCode = "F".charCodeAt(0);
            for (i = 0; i < s.length; i++) {
                value *= 16;
                currentCharCode = s[i].charCodeAt(0);
                if (zeroCharCode <= currentCharCode && currentCharCode <= nineCharCode) {
                    value += (currentCharCode - zeroCharCode);
                }
                else if (aCharCode <= currentCharCode && currentCharCode <= fCharCode) {
                    value += (currentCharCode - aCharCode) + 10;
                }
                else if (ACharCode <= currentCharCode && currentCharCode <= FCharCode) {
                    value += (currentCharCode - ACharCode) + 10;
                }
                else {
                    return {
                        p3: 0,
                        ret: false
                    };
                }
            }
        }
        else {
            for (i = 0; i < s.length; i++) {
                value *= 10;
                currentCharCode = s[i].charCodeAt(0);
                if (zeroCharCode <= currentCharCode && currentCharCode <= nineCharCode) {
                    value += (currentCharCode - zeroCharCode);
                }
                else {
                    return {
                        p3: 0,
                        ret: false
                    };
                }
            }
        }
        return {
            p3: value * multiplier,
            ret: true
        };
    }
    return {
        p3: 0,
        ret: false
    };
}
export function parseNumber(s, provider) {
    var r = tryParseNumber1(s, 231, provider);
    if (!r.ret) {
        throw new FormatException(1, "Incorrect number format");
    }
    return r.p3;
}
export function parseInt8_1(s, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, -128, 127);
}
;
export function parseInt8_2(s, style, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, -128, 127, style);
}
;
export function parseInt16_1(s, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, -32768, 32767);
}
;
export function parseInt16_2(s, style, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, -32768, 32767, style);
}
;
export function parseInt32_1(s, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, -2147483648, 2147483647);
}
;
export function parseInt32_2(s, style, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, -2147483648, 2147483647, style);
}
;
export function parseInt64_1(s, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, -9223372036854775808, 9223372036854775807);
}
;
export function parseInt64_2(s, style, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, -9223372036854775808, 9223372036854775807, style);
}
;
export function parseUInt8_1(s, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, 0, 255);
}
;
export function parseUInt8_2(s, style, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, 0, 255, style);
}
;
export function parseUInt16_1(s, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, 0, 65535);
}
;
export function parseUInt16_2(s, style, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, 0, 65535, style);
}
;
export function parseUInt32_1(s, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, 0, 4294967295);
}
;
export function parseUInt32_2(s, style, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, 0, 4294967295, style);
}
;
export function parseUInt64_1(s, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, 0, 18446744073709551615);
}
;
export function parseUInt64_2(s, style, provider) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return parseIntCore(s, provider, 0, 18446744073709551615, style);
}
;
export function parseIntCore(s, provider, min, max, style) {
    if (style === void 0) { style = 7 /* Integer */; }
    var r = tryParseIntCore(s, provider, min, max, style);
    if (!r.ret) {
        throw new FormatException(1, "Incorrect number format");
    }
    return r.p3;
}
;
export function tryParseInt8_1(s, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, null, -128, 127);
}
;
export function tryParseInt8_2(s, style, provider, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, provider, -128, 127, style);
}
;
export function tryParseInt16_1(s, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, null, -32768, 32767);
}
;
export function tryParseInt16_2(s, style, provider, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, provider, -32768, 32767, style);
}
;
export function tryParseInt32_1(s, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, null, -2147483648, 2147483647);
}
;
export function tryParseInt32_2(s, style, provider, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, provider, -2147483648, 2147483647, style);
}
;
export function tryParseInt64_1(s, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, null, -9223372036854775808, 9223372036854775807);
}
;
export function tryParseInt64_2(s, style, provider, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, provider, -9223372036854775808, 9223372036854775807, style);
}
;
export function tryParseUInt8_1(s, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, null, 0, 255);
}
;
export function tryParseUInt8_2(s, style, provider, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, provider, 0, 255, style);
}
;
export function tryParseUInt16_1(s, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, null, 0, 65535);
}
;
export function tryParseUInt16_2(s, style, provider, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, provider, 0, 65535, style);
}
;
export function tryParseUInt32_1(s, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, null, 0, 4294967295);
}
;
export function tryParseUInt32_2(s, style, provider, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, provider, 0, 4294967295, style);
}
;
export function tryParseUInt64_1(s, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, null, 0, 18446744073709551615);
}
;
export function tryParseUInt64_2(s, style, provider, value) {
    // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers
    return tryParseIntCore(s, provider, 0, 18446744073709551615, style);
}
;
export function tryParseIntCore(s, provider, min, max, style) {
    if (style === void 0) { style = 7 /* Integer */; }
    /*jshint eqnull:true */
    /*jslint bitwise: true */
    //style = style != null ? style : NumberStyles.integer; // Don't use || here, because 0 could be a valid style
    provider = provider || CultureInfo.currentCulture;
    var r = tryParseNumber1(s, style, provider);
    if ((style & 512 /* AllowHexSpecifier */) && max < r.p3) {
        r.p3 -= (-min * 2);
    }
    if (!r.ret || r.p3 < min || max < r.p3 || r.p3 % 1 !== 0) {
        return {
            p1: 0,
            p3: 0,
            ret: false
        };
    }
    var ret = {
        p1: r.p3,
        p3: r.p3,
        ret: r.ret
    };
    return ret;
}
export function numberToString(number, provider) {
    return numberToString2(number, "G", provider);
}
;
var gFormatOptions = { useGrouping: false, maximumSignificantDigits: 15 };
var zeroFormatOptions = {
    useGrouping: false,
    maximumSignificantDigits: 15,
    maximumFractionDigits: 0
};
export function numberToString2(number, format, provider) {
    provider = provider || CultureInfo.currentCulture;
    switch (format) {
        case "G":
            return number.toLocaleString(provider.name, gFormatOptions);
        case "R":
        case "r":
            return number.toString()
                .replace(".", provider.numberFormat.numberDecimalSeparator);
    }
    if (format.match(/[0\#\.]+/)) {
        var isValid = true;
        var formatIndexOfDecimalSeparator = format.indexOf(".");
        var decimalFormat = formatIndexOfDecimalSeparator == -1 ? "" :
            format.substring(formatIndexOfDecimalSeparator + 1);
        var numberString = number.toFixed(decimalFormat.length).toString();
        var numberIndexOfDecimalSeparator = numberString.indexOf(".");
        var integralPart = numberIndexOfDecimalSeparator == -1 ? numberString :
            numberString.substring(0, numberIndexOfDecimalSeparator);
        var integralFormat = formatIndexOfDecimalSeparator == -1 ? format :
            format.substring(0, formatIndexOfDecimalSeparator);
        while (integralFormat.length < integralPart.length) {
            integralFormat = "0" + integralFormat;
        }
        while (integralPart.length < integralFormat.length) {
            integralPart = "0" + integralPart;
        }
        var formattedIntegralPart = "";
        var digit;
        for (var ii = integralFormat.length - 1; ii >= 0; ii--) {
            if (integralFormat[ii] == "0") {
                formattedIntegralPart = integralPart[ii] + formattedIntegralPart;
            }
            else if (integralFormat[ii] == "#") {
                digit = integralPart.substring(0, ii + 1).match(/[1-9]/) ?
                    integralPart[ii] : "";
                formattedIntegralPart = digit + formattedIntegralPart;
            }
            else {
                isValid = false;
            }
        }
        var decimalPart = numberIndexOfDecimalSeparator == -1 ? "" :
            numberString.substring(numberIndexOfDecimalSeparator + 1);
        var formattedDecimalPart = "";
        for (var jj = 0; jj < decimalFormat.length; jj++) {
            if (decimalFormat[jj] == "0") {
                formattedDecimalPart += decimalPart[jj];
            }
            else if (decimalFormat[jj] == "#") {
                digit = decimalPart.length > jj && (decimalPart[jj] != "0" || decimalPart.substring(jj).match(/[1-9]/)) ?
                    decimalPart[jj] : "";
                formattedDecimalPart += digit;
            }
            else {
                isValid = false;
            }
        }
        if (isValid) {
            return formattedIntegralPart +
                (formattedDecimalPart.length > 0 ? "." + formattedDecimalPart : "");
        }
    }
    throw new FormatException(1, "Unsupported format code: " + format);
}
export function intToString(number, provider) {
    return intToString1(number, "G", provider);
}
;
export function intToString1(number, format, provider) {
    provider = provider || CultureInfo.currentCulture;
    if (format && format.length) {
        if (format[0] == "X") {
            number = intSToU(number);
            var result = number.toString(16).toUpperCase();
            if (format.length !== 1) {
                var digits = +format.substr(1);
                if (!isFinite(digits)) {
                    throw new Error("Unsupported format code: " + format);
                }
                while (result.length < digits) {
                    result = "0" + result;
                }
            }
            return result;
        }
    }
    switch (format) {
        case "G":
            return number.toLocaleString(provider.name, gFormatOptions);
    }
    throw new Error("Unsupported format code: " + format);
}
export function intSToU(number) {
    if (number < 0) {
        number = number + 1 + 0xFFFFFFFF;
    }
    return number;
}
export function u32BitwiseAnd(a, b) {
    var r = a & b;
    if (r < 0) {
        r += 4294967296;
    }
    return r;
}
export function u32BitwiseOr(a, b) {
    var r = a | b;
    if (r < 0) {
        r += 4294967296;
    }
    return r;
}
export function u32BitwiseXor(a, b) {
    var r = a ^ b;
    if (r < 0) {
        r += 4294967296;
    }
    return r;
}
export function u32LS(a, b) {
    var r = a << b;
    if (r < 0) {
        r += 4294967296;
    }
    return r;
}
export function decimalAdjust(type, value, exp) {
    // If the exp is undefined or zero...
    if (typeof exp === "undefined" || +exp === 0) {
        return Math[type](value);
    }
    value = +value;
    exp = +exp;
    // If the value is not a number or the exp is not an integer...
    if (isNaN(value) || !(typeof exp === "number" && exp % 1 === 0)) {
        return NaN;
    }
    // Shift
    value = value.toString().split("e");
    value = Math[type](+(value[0] + "e" + (value[1] ? (+value[1] - exp) : -exp)));
    // Shift back
    value = value.toString().split("e");
    return +(value[0] + "e" + (value[1] ? (+value[1] + exp) : exp));
}
export function round10(value, exp) {
    return decimalAdjust("round", value, exp);
}
export function round10N(value, exp) {
    return decimalAdjust("round", value, -exp);
}
export function floor10(value, exp) {
    return decimalAdjust("floor", value, exp);
}
export function ceil10(value, exp) {
    return decimalAdjust("ceil", value, exp);
}
//# sourceMappingURL=numberExtended.js.map