/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Codes
 */
import { Id64, JsonUtils } from "@itwin/core-bentley";
/**
 * A three-part structure containing information about the [Code]($docs/bis/guide/fundamentals/codes) of an Element
 * @public
 */
export class Code {
    /** The id of the [CodeSpec]($docs/bis/guide/fundamentals/codes.md#codespec) of the Element */
    spec;
    /** The [CodeScope]($docs/bis/guide/fundamentals/codes.md#codescope-property) of the Element */
    scope;
    /** The [CodeValue]($docs/bis/guide/fundamentals/codes.md#codevalue-property) of the Element
     * @note Leading and trailing whitespace is invalid so is automatically trimmed.
     */
    get value() { return this._value ?? ""; }
    set value(val) { this._value = val?.trim(); }
    _value;
    constructor(codeProps) {
        this.spec = Id64.fromJSON(codeProps.spec);
        this.scope = JsonUtils.asString(codeProps.scope);
        this.value = JsonUtils.asString(codeProps.value);
    }
    /** Create an empty, non-unique code with no special meaning. */
    static createEmpty() {
        const id = Id64.fromLocalAndBriefcaseIds(1, 0);
        return new Code({ spec: id, scope: id });
    }
    static fromJSON(json) { return json ? new Code(json) : Code.createEmpty(); }
    toJSON() { return { spec: this.spec, scope: this.scope, value: this.value }; }
    equals(other) { return Code.equalCodes(this, other); }
    /** @internal */
    static equalCodes(c1, c2) {
        return c1.spec === c2.spec && c1.scope === c2.scope && c1.value === c2.value;
    }
    /** Determine whether this Code is valid. */
    static isValid(c) { return Id64.isValidId64(c.spec); }
    /** Determine if this code is valid but not otherwise meaningful (and therefore not necessarily unique) */
    static isEmpty(c) { return this.isValid(c) && (c.value === undefined || c.value === ""); }
    toString() { return `[Code: ${this.spec}, ${this.scope}, ${this.value}]`; }
}
/** Names of the internal BIS CodeSpecs. These names match those specified by the native library.
 * For other domains, the best practice is to include the domain name or alias as part of the CodeSpec name to ensure global uniqueness.
 * @public
* @extensions
* @see [CodeSpec]($docs/bis/guide/fundamentals/codes.md#codespec)
 */
export var BisCodeSpec;
(function (BisCodeSpec) {
    /** The name of the standard [[CodeSpec]] used when creating *empty* codes.
     * @see [[Code.createEmpty]]
     */
    BisCodeSpec["nullCodeSpec"] = "bis:NullCodeSpec";
    /** @internal */
    BisCodeSpec["annotationFrameStyle"] = "bis:AnnotationFrameStyle";
    /** @internal */
    BisCodeSpec["annotationLeaderStyle"] = "bis:AnnotationLeaderStyle";
    /** @internal */
    BisCodeSpec["annotationTextStyle"] = "bis:AnnotationTextStyle";
    /** The name of the standard [[CodeSpec]] used when creating codes for [AuxCoordSystem2d]($backend) elements.
     * @see [AuxCoordSystem2d.createCode]($backend)
     */
    BisCodeSpec["auxCoordSystem2d"] = "bis:AuxCoordSystem2d";
    /** The name of the standard [[CodeSpec]] used when creating codes for [AuxCoordSystem3d]($backend) elements.
     * @see [AuxCoordSystem3d.createCode]($backend)
     */
    BisCodeSpec["auxCoordSystem3d"] = "bis:AuxCoordSystem3d";
    /** The name of the standard [[CodeSpec]] used when creating codes for [AuxCoordSystemSpatial]($backend) elements.
     * @see [AuxCoordSystemSpatial.createCode]($backend)
     */
    BisCodeSpec["auxCoordSystemSpatial"] = "bis:AuxCoordSystemSpatial";
    /** The name of the standard [[CodeSpec]] used when creating codes for [CategorySelector]($backend) elements.
     * @see [CategorySelector.createCode]($backend)
     */
    BisCodeSpec["categorySelector"] = "bis:CategorySelector";
    /** @internal */
    BisCodeSpec["colorBook"] = "bis:ColorBook";
    /** The name of the standard [[CodeSpec]] used when creating codes for [DisplayStyle]($backend) elements.
     * @see [DisplayStyle.createCode]($backend)
     */
    BisCodeSpec["displayStyle"] = "bis:DisplayStyle";
    /** The name of the standard [[CodeSpec]] used when creating codes for [Drawing]($backend) elements.
     * @see [Drawing.createCode]($backend)
     */
    BisCodeSpec["drawing"] = "bis:Drawing";
    /** The name of the standard [[CodeSpec]] used when creating codes for [DrawingCategory]($backend) elements.
     * @see [DrawingCategory.createCode]($backend)
     */
    BisCodeSpec["drawingCategory"] = "bis:DrawingCategory";
    /** The name of the standard [[CodeSpec]] used when creating codes for [ExternalSource]($backend) elements.
     * @note This CodeSpec is not automatically created, so use [ExternalSource.ensureCodeSpec]($backend) to make sure that it exists.
     * @see [ExternalSource.createCode]($backend)
     */
    BisCodeSpec["externalSource"] = "bis:ExternalSource";
    /** The name of the standard [[CodeSpec]] used when creating codes for [ExternalSourceAttachment]($backend) elements.
     * @note This CodeSpec is not automatically created, so use [ExternalSourceAttachment.ensureCodeSpec]($backend) to make sure that it exists.
     * @see [ExternalSource.createCode]($backend)
     */
    BisCodeSpec["externalSourceAttachment"] = "bis:ExternalSourceAttachment";
    /** The name of the standard [[CodeSpec]] used when creating codes for [GeometryPart]($backend) elements.
     * @see [GeometryPart.createCode]($backend)
     */
    BisCodeSpec["geometryPart"] = "bis:GeometryPart";
    /** The name of the standard [[CodeSpec]] used when creating codes for [GraphicalType2d]($backend) elements.
     * @see [GraphicalType2d.createCode]($backend)
     */
    BisCodeSpec["graphicalType2d"] = "bis:GraphicalType2d";
    /** The name of the standard [[CodeSpec]] used when creating codes for [LineStyle]($backend) elements.
     * @see [LineStyle.createCode]($backend)
     */
    BisCodeSpec["lineStyle"] = "bis:LineStyle";
    /** The name of the standard [[CodeSpec]] used when creating codes for [LinkElement]($backend) elements.
     * @see [LinkElement.createCode]($backend)
     */
    BisCodeSpec["linkElement"] = "bis:LinkElement";
    /** The name of the standard [[CodeSpec]] used when creating codes for [ModelSelector]($backend) elements.
     * @see [ModelSelector.createCode]($backend)
     */
    BisCodeSpec["modelSelector"] = "bis:ModelSelector";
    /** The name of the standard [[CodeSpec]] used when creating codes for [PhysicalMaterial]($backend) elements.
     * @see [PhysicalMaterial.createCode]($backend)
     */
    BisCodeSpec["physicalMaterial"] = "bis:PhysicalMaterial";
    /** The name of the standard [[CodeSpec]] used when creating codes for [PhysicalType]($backend) elements.
     * @see [PhysicalType.createCode]($backend)
     */
    BisCodeSpec["physicalType"] = "bis:PhysicalType";
    /** The name of the standard [[CodeSpec]] used when creating codes for [InformationPartitionElement]($backend) elements.
     * @see [InformationPartitionElement.createCode]($backend)
     */
    BisCodeSpec["informationPartitionElement"] = "bis:InformationPartitionElement";
    /** The name of the standard [[CodeSpec]] used when creating codes for [RenderMaterialElement]($backend) elements.
     * @see [RenderMaterialElement.createCode]($backend)
     */
    BisCodeSpec["renderMaterial"] = "bis:RenderMaterial";
    /** The name of the standard [[CodeSpec]] used when creating codes for [Sheet]($backend) elements.
     * @see [Sheet.createCode]($backend)
     */
    BisCodeSpec["sheet"] = "bis:Sheet";
    /** The name of the standard [[CodeSpec]] used when creating codes for [SheetIndex]($backend) elements.
     * @see [SheetIndex.createCode]($backend)
     */
    BisCodeSpec["sheetIndex"] = "bis:SheetIndex";
    /** The name of the standard [[CodeSpec]] used when creating codes for [SheetIndexEntry]($backend) elements.
     * @see [SheetIndexEntry.createCode]($backend)
     */
    BisCodeSpec["sheetIndexEntry"] = "bis:SheetIndexEntry";
    /** The name of the standard [[CodeSpec]] used when creating codes for [SpatialCategory]($backend) elements.
     * @see [SpatialCategory.createCode]($backend)
     */
    BisCodeSpec["spatialCategory"] = "bis:SpatialCategory";
    /** The name of the standard [[CodeSpec]] used when creating codes for [SpatialLocationType]($backend) elements.
     * @see [SpatialLocationType.createCode]($backend)
     */
    BisCodeSpec["spatialLocationType"] = "bis:SpatialLocationType";
    /** The name of the standard [[CodeSpec]] used when creating codes for [SubCategory]($backend) elements.
     * @see [SubCategory.createCode]($backend)
     */
    BisCodeSpec["subCategory"] = "bis:SubCategory";
    /** The name of the standard [[CodeSpec]] used when creating codes for [Subject]($backend) elements.
     * @see [Subject.createCode]($backend)
     */
    BisCodeSpec["subject"] = "bis:Subject";
    /** The name of the standard [[CodeSpec]] used when creating codes for [TemplateRecipe2d]($backend) elements.
     * @see [TemplateRecipe2d.createCode]($backend)
     */
    BisCodeSpec["templateRecipe2d"] = "bis:TemplateRecipe2d";
    /** The name of the standard [[CodeSpec]] used when creating codes for [TemplateRecipe3d]($backend) elements.
     * @see [TemplateRecipe3d.createCode]($backend)
     */
    BisCodeSpec["templateRecipe3d"] = "bis:TemplateRecipe3d";
    /** @internal */
    BisCodeSpec["textAnnotationSeed"] = "bis:TextAnnotationSeed";
    /** The name of the standard [[CodeSpec]] used when creating codes for [Texture]($backend) elements.
     * @see [Texture.createCode]($backend)
     */
    BisCodeSpec["texture"] = "bis:Texture";
    /** The name of the standard [[CodeSpec]] used when creating codes for [ViewDefinition]($backend) elements.
     * @see [ViewDefinition.createCode]($backend)
     */
    BisCodeSpec["viewDefinition"] = "bis:ViewDefinition";
})(BisCodeSpec || (BisCodeSpec = {}));
/** The scope of the Code.
 * @public
 */
export var CodeScopeSpec;
(function (CodeScopeSpec) {
    /** The standard ways the CodeScope can be specified.
     * @public
     */
    let Type;
    (function (Type) {
        /** The Code value must be unique within (at least) the iModel repository */
        Type[Type["Repository"] = 1] = "Repository";
        /** The Code value must be unique within the scope of the Model */
        Type[Type["Model"] = 2] = "Model";
        /** The Code value must be unique among other children of the same parent element */
        Type[Type["ParentElement"] = 3] = "ParentElement";
        /** The Code value must be unique among other elements also scoped by the same element */
        Type[Type["RelatedElement"] = 4] = "RelatedElement";
    })(Type = CodeScopeSpec.Type || (CodeScopeSpec.Type = {}));
    /**
     * Requirements for how the CodeScope Element is identified.
     * @public
     */
    let ScopeRequirement;
    (function (ScopeRequirement) {
        /** The ElementId of CodeScope element identifies its scope. Used for Codes that are unique only within a single iModel. */
        ScopeRequirement[ScopeRequirement["ElementId"] = 1] = "ElementId";
        /** The FederationGuid of the CodeScope element identifies its scope. Used for Codes that are globally unique. */
        ScopeRequirement[ScopeRequirement["FederationGuid"] = 2] = "FederationGuid";
    })(ScopeRequirement = CodeScopeSpec.ScopeRequirement || (CodeScopeSpec.ScopeRequirement = {}));
})(CodeScopeSpec || (CodeScopeSpec = {}));
/** A [Code Specification]($docs/bis/guide/references/glossary#codespec) captures the rules for encoding and decoding significant business information into
 * and from a Code (string). This specification is used to generate and validate Codes.
 *
 * A CodeSpec defines the format of a Code for a certain type of Element in an IModel.
 * A CodeSpec can identify an external system that maintains and/or assigns Codes.
 * @public
 */
export class CodeSpec {
    /** The iModel holding this CodeSpec. */
    iModel;
    /** The id of this CodeSpec. */
    id;
    /** The name of this CodeSpec. */
    name;
    /** The JSON properties for this CodeSpec.
     * @note Use the getters and setters instead of accessing this directly.
     * @internal
     */
    properties;
    constructor(iModel, id, name, properties) {
        this.iModel = iModel;
        this.id = id;
        this.name = name;
        this.properties = properties ?? { scopeSpec: { type: CodeScopeSpec.Type.Repository } };
    }
    /** Create a new CodeSpec from the specified parameters
     * > Note: CodeSpec.id will not be valid until inserted
     * @see [CodeSpecs.insert]($backend)
     */
    static create(iModel, name, scopeType, scopeReq) {
        const props = { scopeSpec: { type: scopeType } };
        if (scopeReq)
            props.scopeSpec.fGuidRequired = scopeReq === CodeScopeSpec.ScopeRequirement.FederationGuid;
        return new CodeSpec(iModel, Id64.invalid, name, props);
    }
    /** Create a new CodeSpec directly from JSON. Used internally by the CodeSpecs.load function.
     * @internal
     */
    static createFromJson(iModel, id, name, properties) {
        return new CodeSpec(iModel, id, name, properties);
    }
    /** Will be true if the id of this CodeSpec is valid. */
    get isValid() { return Id64.isValid(this.id); }
    get isExternal() {
        return true === this.properties.scopeSpec.fGuidRequired;
    }
    /** The scope type of this CodeSpec. */
    get scopeType() { return this.properties.scopeSpec.type; }
    set scopeType(scopeType) { this.properties.scopeSpec.type = scopeType; }
    /** Will be `CodeScopeSpec.ScopeRequirement.FederationGuid` if the scoping element is required to have a FederationGuid or
     * CodeScopeSpec.ScopeRequirement.ElementId` otherwise (the default).
     */
    get scopeReq() {
        return this.properties.scopeSpec.fGuidRequired ? CodeScopeSpec.ScopeRequirement.FederationGuid : CodeScopeSpec.ScopeRequirement.ElementId;
    }
    set scopeReq(req) {
        if (CodeScopeSpec.ScopeRequirement.FederationGuid === req)
            this.properties.scopeSpec.fGuidRequired = true;
        else
            this.properties.scopeSpec.fGuidRequired = undefined;
    }
}
//# sourceMappingURL=Code.js.map