/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Polyface
 */
import { Geometry } from "../Geometry";
/**
 * `TaggedNumericConstants` defines enums with constant values for use in tags of [[TaggedNumericData]]
 * @public
 */
export var TaggedNumericConstants;
(function (TaggedNumericConstants) {
    /**  Reserved values for the "tagA" member of [[TaggedNumericData]]
    * @public
     *
    */
    let TaggedNumericTagType;
    (function (TaggedNumericTagType) {
        /** `tagA` value identifying a subdivision surface*/
        TaggedNumericTagType[TaggedNumericTagType["SubdivisionSurface"] = -1000] = "SubdivisionSurface";
    })(TaggedNumericTagType = TaggedNumericConstants.TaggedNumericTagType || (TaggedNumericConstants.TaggedNumericTagType = {}));
    /**
     * `tagB` values for supported types of subdivision surfaces
     * @public
     */
    let SubdivisionMethod;
    (function (SubdivisionMethod) {
        SubdivisionMethod[SubdivisionMethod["ChooseBasedOnFacets"] = 0] = "ChooseBasedOnFacets";
        SubdivisionMethod[SubdivisionMethod["CatmullClark"] = 1] = "CatmullClark";
        SubdivisionMethod[SubdivisionMethod["Loop"] = 2] = "Loop";
        SubdivisionMethod[SubdivisionMethod["DooSabin"] = 3] = "DooSabin";
    })(SubdivisionMethod = TaggedNumericConstants.SubdivisionMethod || (TaggedNumericConstants.SubdivisionMethod = {}));
    /**
     * numeric values for subdivision control.  These are entered in the intData array as first of a pair.
     * @public
     */
    let SubdivisionControlCode;
    (function (SubdivisionControlCode) {
        /** pair (FixedDepth, d) indicates subdivision to depth d */
        SubdivisionControlCode[SubdivisionControlCode["FixedDepth"] = -100] = "FixedDepth";
        /** pair (FixedDepth, index) indicates absolute tolerance with value in doubleData[index] */
        SubdivisionControlCode[SubdivisionControlCode["AbsoluteTolerance"] = -101] = "AbsoluteTolerance";
        /** pair (FixedDepth, index) indicates tolerance as a fraction of base mesh range is found in doubleData[index] */
        SubdivisionControlCode[SubdivisionControlCode["FractionOfRangeBoxTolerance"] = -102] = "FractionOfRangeBoxTolerance";
    })(SubdivisionControlCode = TaggedNumericConstants.SubdivisionControlCode || (TaggedNumericConstants.SubdivisionControlCode = {}));
})(TaggedNumericConstants || (TaggedNumericConstants = {}));
/**
 * Structure with 2 integer tags and optional arrays of integers, doubles, points, vectors, and geometry.
 * * In typescript/javascript, all integer numbers that can be non-integer.  Please do not insert non-integers in the integer array.
 * @public
 */
export class TaggedNumericData {
    /** Application specific primary tag.   See reserved values in  [[TaggedNumericConstants]] */
    tagA;
    /** Application specific secondary tag.   See reserved values in  [[TaggedNumericConstants]] */
    tagB;
    constructor(tagA = 0, tagB = 0, intData, doubleData) {
        this.tagA = tagA;
        this.tagB = tagB;
        if (intData)
            this.intData = intData;
        if (doubleData)
            this.doubleData = doubleData;
    }
    /** Integer data with application-specific meaning */
    intData;
    /** Double data with application-specific meaning */
    doubleData;
    /**
       * push a pair of int values on the intData array.
       * @param intA
       * @param intB
       */
    pushIntPair(intA, intB) {
        if (!this.intData)
            this.intData = [];
        this.intData.push(intA);
        this.intData.push(intB);
    }
    /**
     * push a pair of int values on the intData array.
     * @param intA int to push on the intData array, followed by index of valueB in the doubleData array.
     * @param valueB value to push on the doubleData array.
     */
    pushIndexedDouble(intA, valueB) {
        if (!this.intData)
            this.intData = [];
        if (!this.doubleData)
            this.doubleData = [];
        this.intData.push(intA);
        this.intData.push(this.doubleData.length);
        this.doubleData.push(valueB);
    }
    /**
     * Search pairs in the intData array for a pair (targetTag, value).  Return the value, possibly restricted to (minValue,maxValue)
     * @param targetTag
     * @param minValue
     * @param maxValue
     * @param defaultValue
     */
    tagToInt(targetTag, minValue, maxValue, defaultValue) {
        if (this.intData) {
            for (let i = 0; i + 1 < this.intData.length; i += 2) {
                if (this.intData[i] === targetTag)
                    return Math.min(Math.max(this.intData[i + 1], minValue), maxValue);
            }
        }
        return defaultValue;
    }
    /**
     * Search pairs in the intData array for a pair (targetTag, index).  Return getDoubleData[index] value, possibly restricted to (minValue,maxValue)
     * @param targetTag
     * @param minValue
     * @param maxValue
     * @param defaultValue
     */
    tagToIndexedDouble(targetTag, minValue, maxValue, defaultValue) {
        if (this.intData) {
            for (let i = 0; i + 1 < this.intData.length; i += 2) {
                if (this.intData[i] === targetTag) {
                    return Geometry.clamp(this.getDoubleData(this.intData[i + 1], defaultValue), minValue, maxValue);
                }
            }
        }
        return defaultValue;
    }
    /**
     * get doubleData[index], or indicated default if the index is out of range
     * @param index
     * @param defaultValue
     */
    getDoubleData(index, defaultValue) {
        if (this.doubleData && 0 <= index && index < this.doubleData.length)
            return this.doubleData[index];
        return defaultValue;
    }
    /** Apply isAlmostEqual to all members. */
    isAlmostEqual(other) {
        if (other === undefined)
            return false;
        if (this.tagA !== other.tagA)
            return false;
        if (this.tagB !== other.tagB)
            return false;
        return Geometry.exactEqualNumberArrays(this.intData, other.intData)
            && Geometry.almostEqualArrays(this.doubleData, other.doubleData, (a, b) => Geometry.isAlmostEqualNumber(a, b));
    }
    static areAlmostEqual(dataA, dataB) {
        if (dataA === undefined && dataB === undefined)
            return true;
        if (dataA !== undefined && dataB !== undefined)
            return dataA.isAlmostEqual(dataB);
        return false;
    }
    /** Return a deep clone.  */
    clone(result) {
        if (!result)
            result = new TaggedNumericData(this.tagA, this.tagB);
        if (this.intData)
            result.intData = this.intData.slice();
        if (this.doubleData)
            result.doubleData = this.doubleData.slice();
        return result;
    }
}
//# sourceMappingURL=TaggedNumericData.js.map