/*
 * SDK Pullenti Lingvo, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software.
 * This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C#.NET project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

const Utils = require("./../../unisharp/Utils");
const StringBuilder = require("./../../unisharp/StringBuilder");

const ReferentsEqualType = require("./../core/ReferentsEqualType");
const IntOntologyItem = require("./../core/IntOntologyItem");
const Termin = require("./../core/Termin");
const Referent = require("./../Referent");
const ReferentClass = require("./../metadata/ReferentClass");
const GoodAttrType = require("./GoodAttrType");
const AttrMeta = require("./internal/AttrMeta");

/**
 * Атрибут товара
 * 
 */
class GoodAttributeReferent extends Referent {
    
    constructor() {
        super(GoodAttributeReferent.OBJ_TYPENAME);
        this.instanceOf = AttrMeta.GLOBAL_META;
    }
    
    get typ() {
        let str = this.getStringValue(GoodAttributeReferent.ATTR_TYPE);
        if (str === null) 
            return GoodAttrType.UNDEFINED;
        try {
            return GoodAttrType.of(str);
        } catch (ex1998) {
        }
        return GoodAttrType.UNDEFINED;
    }
    set typ(value) {
        this.addSlot(GoodAttributeReferent.ATTR_TYPE, value.toString().toUpperCase(), true, 0);
        return value;
    }
    
    get values() {
        let res = new Array();
        for (const s of this.slots) {
            if (s.typeName === GoodAttributeReferent.ATTR_VALUE && ((typeof s.value === 'string' || s.value instanceof String))) {
                let v = Utils.asString(s.value);
                if (v.indexOf('(') > 0) {
                    if (this.typ === GoodAttrType.NUMERIC) 
                        v = v.substring(0, 0 + v.indexOf('(')).trim();
                }
                res.push(v);
            }
        }
        return res;
    }
    
    get altValues() {
        let res = new Array();
        for (const s of this.slots) {
            if (s.typeName === GoodAttributeReferent.ATTR_ALTVALUE && ((typeof s.value === 'string' || s.value instanceof String))) 
                res.push(Utils.asString(s.value));
        }
        return res;
    }
    
    get units() {
        let res = new Array();
        for (const s of this.slots) {
            if (s.typeName === GoodAttributeReferent.ATTR_UNIT && ((typeof s.value === 'string' || s.value instanceof String))) 
                res.push(Utils.asString(s.value));
        }
        return res;
    }
    
    get ref() {
        return Utils.as(this.getSlotValue(GoodAttributeReferent.ATTR_REF), Referent);
    }
    set ref(value) {
        this.addSlot(GoodAttributeReferent.ATTR_REF, value, true, 0);
        return value;
    }
    
    toStringEx(shortVariant, lang = null, lev = 0) {
        let res = new StringBuilder();
        let _typ = this.typ;
        let nam = this.getStringValue(GoodAttributeReferent.ATTR_NAME);
        if (!shortVariant) {
            if (_typ !== GoodAttrType.UNDEFINED) 
                res.append(AttrMeta.GLOBAL_META.typAttr.convertInnerValueToOuterValue(_typ.toString(), lang)).append((nam === null ? "" : (" (" + nam.toLowerCase() + ")"))).append(": ");
        }
        let s = this.getStringValue(GoodAttributeReferent.ATTR_VALUE);
        if (s !== null) {
            if (_typ === GoodAttrType.KEYWORD || _typ === GoodAttrType.CHARACTER) 
                res.append(s.toLowerCase());
            else if (_typ === GoodAttrType.NUMERIC) {
                let vals = this.values;
                let _units = this.units;
                for (let i = 0; i < vals.length; i++) {
                    if (i > 0) 
                        res.append(" x ");
                    res.append(vals[i]);
                    if (vals.length === _units.length) 
                        res.append(_units[i].toLowerCase());
                    else if (_units.length > 0) 
                        res.append(_units[0].toLowerCase());
                }
            }
            else 
                res.append(s);
        }
        let re = this.ref;
        if (re !== null) 
            res.append(re.toStringEx(shortVariant, lang, 0));
        return res.toString();
    }
    
    canBeEquals(obj, _typ = ReferentsEqualType.WITHINONETEXT) {
        let a = Utils.as(obj, GoodAttributeReferent);
        if (a === null) 
            return false;
        if (a.typ !== this.typ) 
            return false;
        let u1 = this.getStringValue(GoodAttributeReferent.ATTR_UNIT);
        let u2 = a.getStringValue(GoodAttributeReferent.ATTR_UNIT);
        if (u1 !== null && u2 !== null) {
            if (u1 !== u2) {
                if (u1.length === (u2.length + 1) && u1 === (u2 + ".")) {
                }
                else if (u2.length === (u1.length + 1) && u2 === (u1 + ".")) {
                }
                return false;
            }
        }
        let nam1 = this.getStringValue(GoodAttributeReferent.ATTR_NAME);
        let nam2 = a.getStringValue(GoodAttributeReferent.ATTR_NAME);
        if (nam1 !== null || nam2 !== null) {
            if (nam1 !== nam2) 
                return false;
        }
        let eq = false;
        if (this.ref !== null || a.ref !== null) {
            if (this.ref === null || a.ref === null) 
                return false;
            if (!this.ref.canBeEquals(a.ref, _typ)) 
                return false;
            eq = true;
        }
        if (this.typ !== GoodAttrType.NUMERIC) {
            for (const s of this.slots) {
                if (s.typeName === GoodAttributeReferent.ATTR_VALUE || s.typeName === GoodAttributeReferent.ATTR_ALTVALUE) {
                    if (a.findSlot(GoodAttributeReferent.ATTR_VALUE, s.value, true) !== null || a.findSlot(GoodAttributeReferent.ATTR_ALTVALUE, s.value, true) !== null) {
                        eq = true;
                        break;
                    }
                }
            }
        }
        else {
            let vals1 = this.values;
            let vals2 = a.values;
            if (vals1.length !== vals2.length) 
                return false;
            for (const v of vals1) {
                if (!vals2.includes(v)) 
                    return false;
            }
        }
        if (!eq) 
            return false;
        return true;
    }
    
    mergeSlots(obj, mergeStatistic = true) {
        super.mergeSlots(obj, mergeStatistic);
        for (let i = this.slots.length - 1; i >= 0; i--) {
            if (this.slots[i].typeName === GoodAttributeReferent.ATTR_ALTVALUE) {
                if (this.findSlot(GoodAttributeReferent.ATTR_VALUE, this.slots[i].value, true) !== null) 
                    this.slots.splice(i, 1);
            }
        }
    }
    
    createOntologyItem() {
        let re = new IntOntologyItem(this);
        for (const s of this.slots) {
            if (s.typeName === GoodAttributeReferent.ATTR_VALUE || s.typeName === GoodAttributeReferent.ATTR_ALTVALUE) 
                re.termins.push(new Termin(Utils.asString(s.value)));
        }
        return re;
    }
    
    static static_constructor() {
        GoodAttributeReferent.OBJ_TYPENAME = "GOODATTR";
        GoodAttributeReferent.ATTR_TYPE = "TYPE";
        GoodAttributeReferent.ATTR_VALUE = "VALUE";
        GoodAttributeReferent.ATTR_ALTVALUE = "ALTVALUE";
        GoodAttributeReferent.ATTR_UNIT = "UNIT";
        GoodAttributeReferent.ATTR_NAME = "NAME";
        GoodAttributeReferent.ATTR_REF = "REF";
    }
}


GoodAttributeReferent.static_constructor();

module.exports = GoodAttributeReferent