import { __assign, __read, __spread, __values } from "tslib";
export var EPriceType;
(function (EPriceType) {
    /** There are no prices included or if, they should be ignored */
    EPriceType[EPriceType["None"] = 0] = "None";
    /** The included prices are purchase ("EK") prices */
    EPriceType[EPriceType["Purchase"] = 1] = "Purchase";
    /** The included prices are sales ("VK") prices */
    EPriceType[EPriceType["Sales"] = 2] = "Sales";
})(EPriceType || (EPriceType = {}));
/**
 * All possible types of price entries per article
 */
export var EPriceLevel;
(function (EPriceLevel) {
    /** Base price */
    EPriceLevel[EPriceLevel["Base"] = 0] = "Base";
    /** Addition price, if currency is %, calculate absolute value on base
     *  price
     */
    EPriceLevel[EPriceLevel["AddToBase"] = 1] = "AddToBase";
    /** Addition price, if currency is %, calculate absolute value on the
     *  sum of base price and all additional prices
     */
    EPriceLevel[EPriceLevel["AddToSum"] = 2] = "AddToSum";
})(EPriceLevel || (EPriceLevel = {}));
/**
 * All possible types of properties
 */
export var EPropertyType;
(function (EPropertyType) {
    EPropertyType[EPropertyType["Bool"] = 0] = "Bool";
    EPropertyType[EPropertyType["Float"] = 1] = "Float";
    EPropertyType[EPropertyType["Int"] = 2] = "Int";
    EPropertyType[EPropertyType["String"] = 3] = "String";
    EPropertyType[EPropertyType["Material"] = 4] = "Material";
})(EPropertyType || (EPropertyType = {}));
/**
 * How condition operators can be compared
 */
export var EConditionCompare;
(function (EConditionCompare) {
    /** op1 == op2 */
    EConditionCompare[EConditionCompare["Equal"] = 10] = "Equal";
    /** op1 > op2 */
    EConditionCompare[EConditionCompare["Greater"] = 11] = "Greater";
    /** op1 >= op2 */
    EConditionCompare[EConditionCompare["GreaterOrEqual"] = 12] = "GreaterOrEqual";
    /** op1 < op2 */
    EConditionCompare[EConditionCompare["Smaller"] = 13] = "Smaller";
    /** op1 <= op2 */
    EConditionCompare[EConditionCompare["SmallerOrEqual"] = 14] = "SmallerOrEqual";
    /** op1 IN [a, b, c] */
    EConditionCompare[EConditionCompare["In"] = 15] = "In";
})(EConditionCompare || (EConditionCompare = {}));
/**
 * How conditions can be chained. op1 and op2 have to be of type ICondition
 */
export var EConditionJoin;
(function (EConditionJoin) {
    EConditionJoin[EConditionJoin["AND"] = 1] = "AND";
    EConditionJoin[EConditionJoin["OR"] = 2] = "OR";
    EConditionJoin[EConditionJoin["PLUS"] = 3] = "PLUS";
    EConditionJoin[EConditionJoin["MINUS"] = 4] = "MINUS";
    EConditionJoin[EConditionJoin["MUL"] = 5] = "MUL";
    EConditionJoin[EConditionJoin["DIV"] = 6] = "DIV";
})(EConditionJoin || (EConditionJoin = {}));
export var EPropertyValueUnitGroup;
(function (EPropertyValueUnitGroup) {
    EPropertyValueUnitGroup["LENGTH"] = "LENGTH";
    EPropertyValueUnitGroup["AREA"] = "AREA";
    EPropertyValueUnitGroup["VOL"] = "VOL";
    EPropertyValueUnitGroup["MASS"] = "MASS";
    EPropertyValueUnitGroup["ANGLE"] = "ANGLE";
})(EPropertyValueUnitGroup || (EPropertyValueUnitGroup = {}));
export var EPropertyValueUnit;
(function (EPropertyValueUnit) {
    /** Meter */
    EPropertyValueUnit[EPropertyValueUnit["LENGTH_M"] = 100] = "LENGTH_M";
    /** Centimeter */
    EPropertyValueUnit[EPropertyValueUnit["LENGTH_CM"] = 101] = "LENGTH_CM";
    /** Millimeter */
    EPropertyValueUnit[EPropertyValueUnit["LENGTH_MM"] = 102] = "LENGTH_MM";
    /** Feet */
    EPropertyValueUnit[EPropertyValueUnit["LENGTH_FT"] = 103] = "LENGTH_FT";
    /** Inches */
    EPropertyValueUnit[EPropertyValueUnit["LENGTH_IN"] = 104] = "LENGTH_IN";
    /** Square Meter */
    EPropertyValueUnit[EPropertyValueUnit["AREA_M2"] = 200] = "AREA_M2";
    /** Square Centimeter */
    EPropertyValueUnit[EPropertyValueUnit["AREA_CM2"] = 201] = "AREA_CM2";
    /** Square Millimeter */
    EPropertyValueUnit[EPropertyValueUnit["AREA_MM2"] = 202] = "AREA_MM2";
    /** Square Feet */
    EPropertyValueUnit[EPropertyValueUnit["AREA_FT2"] = 203] = "AREA_FT2";
    /** Square Inches */
    EPropertyValueUnit[EPropertyValueUnit["AREA_IN2"] = 204] = "AREA_IN2";
    /** Cubic Meter */
    EPropertyValueUnit[EPropertyValueUnit["VOL_M3"] = 300] = "VOL_M3";
    /** Cubic Centimeter */
    EPropertyValueUnit[EPropertyValueUnit["VOL_CM3"] = 301] = "VOL_CM3";
    /** Cubic Millimeter */
    EPropertyValueUnit[EPropertyValueUnit["VOL_MM3"] = 302] = "VOL_MM3";
    /** Cubic Foot */
    EPropertyValueUnit[EPropertyValueUnit["VOL_FT3"] = 303] = "VOL_FT3";
    /** Cubic Inches */
    EPropertyValueUnit[EPropertyValueUnit["VOL_IN3"] = 304] = "VOL_IN3";
    /** Liter */
    EPropertyValueUnit[EPropertyValueUnit["VOL_L"] = 305] = "VOL_L";
    /** US Gallon */
    EPropertyValueUnit[EPropertyValueUnit["VOL_GAL"] = 306] = "VOL_GAL";
    /** Metric Kilogram */
    EPropertyValueUnit[EPropertyValueUnit["MASS_KG"] = 400] = "MASS_KG";
    /** Metric gram */
    EPropertyValueUnit[EPropertyValueUnit["MASS_G"] = 401] = "MASS_G";
    /** Metric Milligram */
    EPropertyValueUnit[EPropertyValueUnit["MASS_MG"] = 402] = "MASS_MG";
    /** Metric Ton */
    EPropertyValueUnit[EPropertyValueUnit["MASS_T"] = 403] = "MASS_T";
    /** US Pounds */
    EPropertyValueUnit[EPropertyValueUnit["MASS_LBS"] = 404] = "MASS_LBS";
    /** US Ounces */
    EPropertyValueUnit[EPropertyValueUnit["MASS_OZ"] = 405] = "MASS_OZ";
    /** Angle (Degree) */
    EPropertyValueUnit[EPropertyValueUnit["ANGLE_DEG"] = 500] = "ANGLE_DEG";
})(EPropertyValueUnit || (EPropertyValueUnit = {}));
var DEFAULT_GROUP_DESCRIPTION = {
    Key: "default",
};
/**
 * Creates a list of groups using the group definition of the properties.
 *
 * All properties without a definition will be added to a default group. This default group
 * can be identified using the value of its IsDefault property.
 *
 * @param {IProperty[]} properties
 * @returns
 */
export var createPropertyGroups = function (properties) {
    var e_1, _a;
    var groups = new Map();
    try {
        for (var properties_1 = __values(properties), properties_1_1 = properties_1.next(); !properties_1_1.done; properties_1_1 = properties_1.next()) {
            var property = properties_1_1.value;
            var description = property.Group !== undefined
                ? property.Group
                : DEFAULT_GROUP_DESCRIPTION;
            var group = groups.get(description.Key);
            if (group === undefined) {
                group = __assign(__assign({}, description), { IsDefault: description === DEFAULT_GROUP_DESCRIPTION, Properties: [] });
                groups.set(description.Key, group);
            }
            group.Properties.push(property);
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (properties_1_1 && !properties_1_1.done && (_a = properties_1.return)) _a.call(properties_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
    return Array.from(groups.values());
};
var DEFAULT_SECTION_DESCRIPTION = {
    Key: "default",
};
/**
 * Creates a list of sections using the section definition of the properties values.
 *
 * All values without a definition will be added to a default section. This default section
 * can be identified using the value of its IsDefault property.
 *
 * @param {IProperty} property
 */
export var createPropertyValueSections = function (property) {
    var e_2, _a;
    var sections = new Map();
    try {
        for (var _b = __values(property.Values), _c = _b.next(); !_c.done; _c = _b.next()) {
            var value = _c.value;
            var description = value.Section !== undefined
                ? value.Section
                : DEFAULT_SECTION_DESCRIPTION;
            var section = sections.get(description.Key);
            if (section === undefined) {
                section = __assign(__assign({}, description), { IsDefault: description === DEFAULT_SECTION_DESCRIPTION, Values: [] });
                sections.set(description.Key, section);
            }
            section.Values.push(value);
        }
    }
    catch (e_2_1) { e_2 = { error: e_2_1 }; }
    finally {
        try {
            if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
        }
        finally { if (e_2) throw e_2.error; }
    }
    return Array.from(sections.values());
};
export var normalizePropertyValueChanges = function (rawChanges) {
    if (Array.isArray(rawChanges)) {
        return rawChanges;
    }
    var changes = [];
    for (var key in rawChanges) {
        changes.push({
            key: key,
            value: rawChanges[key],
        });
    }
    return changes;
};
/**
 * Merges two property value changes
 *
 * @param {PropertyValueChanges} a
 * @param {PropertyValueChanges} b
 * @returns {PropertyValueChanges[]}
 */
export var mergePropertyValueChanges = function (a, b) {
    var e_3, _a, e_4, _b;
    var aNormalized = normalizePropertyValueChanges(a);
    var bNormalized = normalizePropertyValueChanges(b);
    var result = new Map();
    try {
        for (var aNormalized_1 = __values(aNormalized), aNormalized_1_1 = aNormalized_1.next(); !aNormalized_1_1.done; aNormalized_1_1 = aNormalized_1.next()) {
            var _c = aNormalized_1_1.value, key = _c.key, value = _c.value;
            result.set(key, value);
        }
    }
    catch (e_3_1) { e_3 = { error: e_3_1 }; }
    finally {
        try {
            if (aNormalized_1_1 && !aNormalized_1_1.done && (_a = aNormalized_1.return)) _a.call(aNormalized_1);
        }
        finally { if (e_3) throw e_3.error; }
    }
    try {
        for (var bNormalized_1 = __values(bNormalized), bNormalized_1_1 = bNormalized_1.next(); !bNormalized_1_1.done; bNormalized_1_1 = bNormalized_1.next()) {
            var _d = bNormalized_1_1.value, key = _d.key, value = _d.value;
            result.set(key, value);
        }
    }
    catch (e_4_1) { e_4 = { error: e_4_1 }; }
    finally {
        try {
            if (bNormalized_1_1 && !bNormalized_1_1.done && (_b = bNormalized_1.return)) _b.call(bNormalized_1);
        }
        finally { if (e_4) throw e_4.error; }
    }
    return Array.from(result, function (_a) {
        var _b = __read(_a, 2), key = _b[0], value = _b[1];
        return ({ key: key, value: value });
    });
};
/**
 * Creates a flat configuration object from a list of changes
 *
 * @param {PropertyValueChanges} changes
 * @returns
 */
export var createArticleConfigurationValuesFromChanges = function (changes) {
    var e_5, _a;
    var normalizedChanges = normalizePropertyValueChanges(changes);
    var configuration = {};
    try {
        for (var normalizedChanges_1 = __values(normalizedChanges), normalizedChanges_1_1 = normalizedChanges_1.next(); !normalizedChanges_1_1.done; normalizedChanges_1_1 = normalizedChanges_1.next()) {
            var _b = normalizedChanges_1_1.value, key = _b.key, value = _b.value;
            configuration[key] = value;
        }
    }
    catch (e_5_1) { e_5 = { error: e_5_1 }; }
    finally {
        try {
            if (normalizedChanges_1_1 && !normalizedChanges_1_1.done && (_a = normalizedChanges_1.return)) _a.call(normalizedChanges_1);
        }
        finally { if (e_5) throw e_5.error; }
    }
    return configuration;
};
var PROPERTY_PATH_PART_SEPERATOR = "@@";
export var createPropertyKey = function (path) {
    return path.join(PROPERTY_PATH_PART_SEPERATOR);
};
export var getPropertyNamesFromKey = function (propertyKey) {
    var segments = propertyKey.split(PROPERTY_PATH_PART_SEPERATOR);
    var result = [];
    for (var index = 0; index < segments.length; index++) {
        result.push(segments.slice(0, index + 1).join(PROPERTY_PATH_PART_SEPERATOR));
    }
    return result;
};
/**
 * Retrieves the actual active value of a property. This can either be a value of the input property, or the value of a subproperty
 *
 * @param {IProperty} property
 * @returns {(IPropertyValue | undefined)}
 */
export var getFinalPropertyValue = function (property) {
    if (property.Value === undefined) {
        return undefined;
    }
    var definition = findValueDefinition(property, property.Value);
    if (definition === undefined || !isProperty(definition)) {
        return definition;
    }
    return getFinalPropertyValue(definition);
};
/**
 * Retrieves a property from the property tree
 *
 * @template T
 * @param {T[]} properties
 * @param {(string | string[])} propertyPathOrKey
 * @returns
 */
export var findProperty = function (properties, propertyPathOrKey) {
    var propertyNames = typeof propertyPathOrKey === "string"
        ? getPropertyNamesFromKey(propertyPathOrKey)
        : propertyPathOrKey;
    var property = properties.find(function (property) { return property.Key === propertyNames[0]; });
    var _loop_1 = function (index) {
        if (property === undefined) {
            return "break";
        }
        property = property.SubProperties.find(function (property) { return property.Key === propertyNames[index]; });
    };
    for (var index = 1; index < propertyNames.length; index++) {
        var state_1 = _loop_1(index);
        if (state_1 === "break")
            break;
    }
    return property;
};
/**
 * Finds the definition for a value inside the properties direct subproperties and values.
 *
 * @param {IProperty} property
 * @param {TPropertyValue} targetValue
 * @returns
 */
export var findValueDefinition = function (property, targetValue) {
    var e_6, _a, e_7, _b;
    var normalizedValue = targetValue.toString();
    try {
        for (var _c = __values(property.Values), _d = _c.next(); !_d.done; _d = _c.next()) {
            var value = _d.value;
            if (value.Value.toString() === normalizedValue) {
                return value;
            }
        }
    }
    catch (e_6_1) { e_6 = { error: e_6_1 }; }
    finally {
        try {
            if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
        }
        finally { if (e_6) throw e_6.error; }
    }
    try {
        for (var _e = __values(property.SubProperties), _f = _e.next(); !_f.done; _f = _e.next()) {
            var subProperty = _f.value;
            if (subProperty.Key === normalizedValue) {
                return subProperty;
            }
        }
    }
    catch (e_7_1) { e_7 = { error: e_7_1 }; }
    finally {
        try {
            if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
        }
        finally { if (e_7) throw e_7.error; }
    }
};
export var isProperty = function (item) { return "Key" in item; };
/**
 * Retrieves all currently active subproperties for a property
 *
 * @param {IProperty} property
 * @returns
 */
export var findActiveSubProperties = function (property) {
    var properties = [];
    var parentProperty = property;
    while (parentProperty.SubProperties.length > 0 &&
        parentProperty.Value !== undefined) {
        var activeDefinition = findValueDefinition(parentProperty, parentProperty.Value);
        if (activeDefinition === undefined || !isProperty(activeDefinition)) {
            break;
        }
        properties.push(activeDefinition);
        parentProperty = activeDefinition;
    }
    return properties;
};
/**
 * Creates a flat list of properties where all active subproperties are listed after their base property
 *
 * @param {IProperty[]} properties
 * @returns
 */
export var createActiveSubPropertyInjectedPropertyList = function (properties) {
    var e_8, _a;
    var result = [];
    try {
        for (var properties_2 = __values(properties), properties_2_1 = properties_2.next(); !properties_2_1.done; properties_2_1 = properties_2.next()) {
            var property = properties_2_1.value;
            result.push.apply(result, __spread([property], findActiveSubProperties(property)));
        }
    }
    catch (e_8_1) { e_8 = { error: e_8_1 }; }
    finally {
        try {
            if (properties_2_1 && !properties_2_1.done && (_a = properties_2.return)) _a.call(properties_2);
        }
        finally { if (e_8) throw e_8.error; }
    }
    return result;
};
/**
 * Creates a fake value representation from a property
 *
 * @param {IProperty} property
 * @returns {IPropertyValue}
 */
export var createFakeValueFromProperty = function (property) { return ({
    Value: property.Key,
    Text: property.Text,
    Image: property.Image,
    Enabled: property.Enabled,
    Visible: property.Visible,
}); };
