"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var ig_utilities_1 = require("@intelligentgraphics/ig.utilities");
var Types_1 = require("./Types");
exports.getDefaultUnitString = function (unit) {
    if (typeof unit === "string") {
        return unit;
    }
    var tR = "";
    switch (unit) {
        case Types_1.EPropertyValueUnit.LENGTH_M:
            tR = "m";
            break;
        case Types_1.EPropertyValueUnit.LENGTH_CM:
            tR = "cm";
            break;
        case Types_1.EPropertyValueUnit.LENGTH_MM:
            tR = "mm";
            break;
        case Types_1.EPropertyValueUnit.LENGTH_FT:
            tR = "ft";
            break;
        case Types_1.EPropertyValueUnit.LENGTH_IN:
            tR = "in";
            break;
        case Types_1.EPropertyValueUnit.AREA_M2:
            tR = "m²";
            break;
        case Types_1.EPropertyValueUnit.AREA_CM2:
            tR = "cm²";
            break;
        case Types_1.EPropertyValueUnit.AREA_MM2:
            tR = "mm²";
            break;
        case Types_1.EPropertyValueUnit.AREA_FT2:
            tR = "sq ft";
            break;
        case Types_1.EPropertyValueUnit.AREA_IN2:
            tR = "sq in";
            break;
        case Types_1.EPropertyValueUnit.VOL_M3:
            tR = "m³";
            break;
        case Types_1.EPropertyValueUnit.VOL_CM3:
            tR = "cm³";
            break;
        case Types_1.EPropertyValueUnit.VOL_MM3:
            tR = "mm³";
            break;
        case Types_1.EPropertyValueUnit.VOL_FT3:
            tR = "cu ft";
            break;
        case Types_1.EPropertyValueUnit.VOL_IN3:
            tR = "cu in";
            break;
        case Types_1.EPropertyValueUnit.VOL_L:
            tR = "l";
            break;
        case Types_1.EPropertyValueUnit.VOL_GAL:
            tR = "gal";
            break;
        case Types_1.EPropertyValueUnit.MASS_KG:
            tR = "kg";
            break;
        case Types_1.EPropertyValueUnit.MASS_G:
            tR = "g";
            break;
        case Types_1.EPropertyValueUnit.MASS_MG:
            tR = "mg";
            break;
        case Types_1.EPropertyValueUnit.MASS_T:
            tR = "t";
            break;
        case Types_1.EPropertyValueUnit.MASS_LBS:
            tR = "lb";
            break;
        case Types_1.EPropertyValueUnit.MASS_OZ:
            tR = "oz";
            break;
        case Types_1.EPropertyValueUnit.ANGLE_DEG:
            tR = "°";
            break;
        default:
            throw new Error("Can not convert unknown unit \"" + unit + "\"");
    }
    return tR;
};
exports.getDefaultUnitPrecision = function (unit) {
    var tR = 1;
    if (unit === undefined || typeof unit === "string") {
        return tR;
    }
    switch (unit) {
        case Types_1.EPropertyValueUnit.LENGTH_M:
            tR = 0.001;
            break;
        case Types_1.EPropertyValueUnit.LENGTH_CM:
            tR = 0.1;
            break;
        case Types_1.EPropertyValueUnit.LENGTH_MM:
            tR = 1;
            break;
        case Types_1.EPropertyValueUnit.LENGTH_FT:
            tR = 1 / 12; // 1ft = 12in, so 3.1415 => 3ft 2in
            break;
        case Types_1.EPropertyValueUnit.LENGTH_IN:
            tR = 1 / 16; // round to 1/16in, so 3.1415 => 3 1/8in
            break;
        case Types_1.EPropertyValueUnit.AREA_M2:
            tR = 0.1;
            break;
        case Types_1.EPropertyValueUnit.AREA_CM2:
            tR = 1;
            break;
        case Types_1.EPropertyValueUnit.AREA_MM2:
            tR = 1;
            break;
        case Types_1.EPropertyValueUnit.AREA_FT2:
            tR = 0.1;
            break;
        case Types_1.EPropertyValueUnit.AREA_IN2:
            tR = 1;
            break;
        case Types_1.EPropertyValueUnit.VOL_M3:
            tR = 0.01;
            break;
        case Types_1.EPropertyValueUnit.VOL_CM3:
            tR = 1;
            break;
        case Types_1.EPropertyValueUnit.VOL_MM3:
            tR = 1;
            break;
        case Types_1.EPropertyValueUnit.VOL_FT3:
            tR = 0.01;
            break;
        case Types_1.EPropertyValueUnit.VOL_IN3:
            tR = 0.1;
            break;
        case Types_1.EPropertyValueUnit.VOL_L:
            tR = 0.1;
            break;
        case Types_1.EPropertyValueUnit.VOL_GAL:
            tR = 0.01;
            break;
        case Types_1.EPropertyValueUnit.MASS_KG:
            tR = 0.01;
            break;
        case Types_1.EPropertyValueUnit.MASS_G:
            tR = 1;
            break;
        case Types_1.EPropertyValueUnit.MASS_MG:
            tR = 1;
            break;
        case Types_1.EPropertyValueUnit.MASS_T:
            tR = 0.001;
            break;
        case Types_1.EPropertyValueUnit.MASS_LBS:
            tR = 0.01;
            break;
        case Types_1.EPropertyValueUnit.MASS_OZ:
            tR = 0.1;
            break;
        case Types_1.EPropertyValueUnit.ANGLE_DEG:
            tR = 1;
            break;
        default:
            throw new Error("Can not convert unknown unit \"" + unit + "\"");
    }
    return tR;
};
exports.getDefaultRoundedValue = function (value, unit) {
    if (unit === undefined || typeof unit === "string") {
        return value;
    }
    var round = function (input, precision) {
        var tR = Math.round(input / precision) * precision;
        return Math.round(tR * 10000) / 10000; // to avoid floating point corner cases like .0000000001
    };
    return round(value, exports.getDefaultUnitPrecision(unit));
};
exports.getUnitValueAsString = function (value, unit, locale) {
    var tVal = exports.getDefaultRoundedValue(value, unit);
    //special case imperial length units
    if (unit === Types_1.EPropertyValueUnit.LENGTH_IN) {
        var tFullInches = Math.floor(tVal);
        var tFracInches = Math.round((tVal - tFullInches) * 16);
        // TODO: shorten fraction
        return (tFullInches.toString() +
            " " +
            tFracInches.toString() +
            "/16" +
            +exports.getDefaultUnitString(unit));
    }
    if (unit === Types_1.EPropertyValueUnit.LENGTH_FT) {
        // TODO: format like "3ft 5 1/8in"
        return tVal.toString() + exports.getDefaultUnitString(unit);
    }
    function log10(v) {
        return Math.log(v) / Math.log(10);
    }
    var tDecimals = log10(Math.round(1 / exports.getDefaultUnitPrecision(unit)));
    return (tVal.toLocaleString(locale, {
        minimumFractionDigits: tDecimals,
    }) + exports.getDefaultUnitString(unit));
};
exports.convert = function (value, from, to) {
    function convertLength() {
        var tMeter;
        switch (from) {
            case Types_1.EPropertyValueUnit.LENGTH_CM:
                tMeter = value / 100.0;
                break;
            case Types_1.EPropertyValueUnit.LENGTH_MM:
                tMeter = value / 1000.0;
                break;
            case Types_1.EPropertyValueUnit.LENGTH_FT:
                tMeter = value / (12 * 0.0254);
                break;
            case Types_1.EPropertyValueUnit.LENGTH_IN:
                tMeter = value / 0.0254;
                break;
            default:
                tMeter = value;
        }
        var tTargetValue = tMeter;
        switch (to) {
            case Types_1.EPropertyValueUnit.LENGTH_M:
                tTargetValue = tMeter;
                break;
            case Types_1.EPropertyValueUnit.LENGTH_CM:
                tTargetValue = tMeter * 100.0;
                break;
            case Types_1.EPropertyValueUnit.LENGTH_MM:
                tTargetValue = tMeter * 1000.0;
                break;
            case Types_1.EPropertyValueUnit.LENGTH_FT:
                tTargetValue = (tMeter * 100) / 2.54 / 12.0;
                break;
            case Types_1.EPropertyValueUnit.LENGTH_IN:
                tTargetValue = (tMeter * 100) / 2.54;
                break;
        }
        return exports.getDefaultRoundedValue(tTargetValue, to);
    }
    var convertArea = function () {
        var tSqM;
        switch (from) {
            case Types_1.EPropertyValueUnit.AREA_CM2:
                tSqM = value / Math.pow(100.0, 2);
                break;
            case Types_1.EPropertyValueUnit.AREA_MM2:
                tSqM = value / Math.pow(1000.0, 2);
                break;
            case Types_1.EPropertyValueUnit.AREA_FT2:
                tSqM = value / Math.pow(12 * 0.0254, 2);
                break;
            case Types_1.EPropertyValueUnit.AREA_IN2:
                tSqM = value / Math.pow(0.0254, 2);
                break;
            default:
                tSqM = value;
        }
        var tTargetValue = tSqM;
        switch (to) {
            case Types_1.EPropertyValueUnit.AREA_M2:
                tTargetValue = tSqM;
                break;
            case Types_1.EPropertyValueUnit.AREA_CM2:
                tTargetValue = tSqM * Math.pow(100.0, 2);
                break;
            case Types_1.EPropertyValueUnit.AREA_MM2:
                tTargetValue = tSqM * Math.pow(1000.0, 2);
                break;
            case Types_1.EPropertyValueUnit.AREA_FT2:
                tTargetValue = tSqM / Math.pow(12 * 0.0254, 2);
                break;
            case Types_1.EPropertyValueUnit.AREA_IN2:
                tTargetValue = tSqM / Math.pow(0.0254, 2);
                break;
        }
        return exports.getDefaultRoundedValue(tTargetValue, to);
    };
    if (from === to) {
        return value;
    }
    var tR;
    switch (exports.getGroupOfUnit(from)) {
        case Types_1.EPropertyValueUnitGroup.LENGTH:
            tR = convertLength();
            break;
        case Types_1.EPropertyValueUnitGroup.AREA:
            tR = convertArea();
            break;
        case Types_1.EPropertyValueUnitGroup.VOL:
            // TODO
            break;
        case Types_1.EPropertyValueUnitGroup.MASS:
            // TODO
            break;
        case Types_1.EPropertyValueUnitGroup.ANGLE:
            break;
    }
    if (tR === undefined) {
        throw new Error("Invalid conversion");
    }
    return tR;
};
exports.getGroupOfUnit = function (unit) {
    var tR;
    switch (unit) {
        // lengths
        case Types_1.EPropertyValueUnit.LENGTH_M:
        case Types_1.EPropertyValueUnit.LENGTH_CM:
        case Types_1.EPropertyValueUnit.LENGTH_MM:
        case Types_1.EPropertyValueUnit.LENGTH_FT:
        case Types_1.EPropertyValueUnit.LENGTH_IN:
            tR = Types_1.EPropertyValueUnitGroup.LENGTH;
            break;
        // areas
        case Types_1.EPropertyValueUnit.AREA_M2:
        case Types_1.EPropertyValueUnit.AREA_CM2:
        case Types_1.EPropertyValueUnit.AREA_MM2:
        case Types_1.EPropertyValueUnit.AREA_FT2:
        case Types_1.EPropertyValueUnit.AREA_IN2:
            tR = Types_1.EPropertyValueUnitGroup.AREA;
            break;
        // volumes
        case Types_1.EPropertyValueUnit.VOL_M3:
        case Types_1.EPropertyValueUnit.VOL_CM3:
        case Types_1.EPropertyValueUnit.VOL_MM3:
        case Types_1.EPropertyValueUnit.VOL_FT3:
        case Types_1.EPropertyValueUnit.VOL_IN3:
        case Types_1.EPropertyValueUnit.VOL_L:
        case Types_1.EPropertyValueUnit.VOL_GAL:
            tR = Types_1.EPropertyValueUnitGroup.VOL;
            break;
        // weights
        case Types_1.EPropertyValueUnit.MASS_KG:
        case Types_1.EPropertyValueUnit.MASS_G:
        case Types_1.EPropertyValueUnit.MASS_MG:
        case Types_1.EPropertyValueUnit.MASS_T:
        case Types_1.EPropertyValueUnit.MASS_LBS:
        case Types_1.EPropertyValueUnit.MASS_OZ:
            tR = Types_1.EPropertyValueUnitGroup.MASS;
            break;
        // angles
        case Types_1.EPropertyValueUnit.ANGLE_DEG:
            tR = Types_1.EPropertyValueUnitGroup.ANGLE;
            break;
    }
    return tR;
};
exports.convertProperty = function (property, from, to) {
    var e_1, _a, e_2, _b;
    if (ig_utilities_1.isNullOrUndefined(from) ||
        ig_utilities_1.isNullOrUndefined(to) ||
        (property.ValueType !== Types_1.EPropertyType.Int &&
            property.ValueType !== Types_1.EPropertyType.Float) ||
        from === to) {
        return;
    }
    var resultProperty = ig_utilities_1.Obj.deepClone(property);
    var keys = ["Value", "ValueRangeFrom", "ValueRangeTo"];
    try {
        for (var keys_1 = tslib_1.__values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
            var key = keys_1_1.value;
            var value = property[key];
            if (typeof value !== "undefined") {
                resultProperty[key] = exports.convert(value, from, to);
            }
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
    try {
        for (var _c = tslib_1.__values(resultProperty.Values), _d = _c.next(); !_d.done; _d = _c.next()) {
            var value = _d.value;
            var convertText = value.Text !== undefined &&
                value.Text.length === 1 &&
                value.Value.toString() === value.Text[0];
            value.Value = exports.convert(value.Value, from, to);
            if (convertText) {
                value.Text = [value.Value.toString()];
            }
        }
    }
    catch (e_2_1) { e_2 = { error: e_2_1 }; }
    finally {
        try {
            if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
        }
        finally { if (e_2) throw e_2.error; }
    }
    resultProperty.ValueUnit = to;
    return resultProperty;
};
