import { BentleyError, GuidString, MarkRequired, Mutable } from "@itwin/core-bentley";
import { CodeProps, FontId, FontType } from "@itwin/core-common";
import { CloudSqlite } from "./CloudSqlite";
import { IModelDb } from "./IModelDb";
import { SettingsContainer } from "./workspace/Settings";
import { VersionedSqliteDb } from "./SQLiteDb";
/**
 * The services for querying, reserving, updating, and deleting codes for a BriefcaseDb (available via `BriefcaseDb.codeService`) whenever it is opened for write access.
 * See [CodeService]($docs/learning/backend/CodeService).
 * @alpha
 */
export interface CodeService {
    /** @internal */
    close: () => void;
    initialize(iModel: IModelDb): Promise<void>;
    /** the index for external Codes for this CodeService */
    readonly externalCodes?: CloudSqlite.DbAccess<CodeService.CodesDb, CodeService.ReadMethods, CodeService.WriteMethods>;
    /** the index for internal Codes for this CodeService */
    readonly internalCodes?: CloudSqlite.DbAccess<CodeService.InternalCodes, CodeService.InternalReadMethods, CodeService.InternalWriteMethods>;
    /**
     * Application-supplied parameters for reserving new codes.
     */
    readonly appParams: CodeService.AuthorAndOrigin;
    /**
     * Verify that the Code of a to-be-inserted or to-be-updated Element:
     * 1. has already been reserved,
     * 2. if the element has a `federationGuid`, it must match the reserved value. If the federationGuid is undefined,
     * the value from the code index is returned.
     *
     * If not, throw an exception. Elements with no CodeValue are ignored.
     * @note this method is automatically called whenever elements are added or updated by a BriefcaseDb with a CodeService.
     */
    verifyCode(props: CodeService.ElementCodeProps): void;
}
/** @alpha */
export declare namespace CodeService {
    interface WriteMethods {
        /** Add a new code spec to this code service.
         */
        addCodeSpec(val: CodeService.NameAndJson): Promise<void>;
        /**
         * Add all of the codes and code specs from this CodeService's BriefcaseDb into the code index.
         * @returns the number of codes actually added.
         * @note It is not necessary to call this method unless the BriefcaseDb somehow becomes out of sync with its CodeService,
         * for example when migrating iModels to a new code service. It is safe (but relatively expensive) to call this method multiple times, since
         * any codes or code specs that are already in the index are ignored.
         */
        addAllCodes(iModel: IModelDb): Promise<number>;
        /**
         * Attempt to reserve a single proposed code.
         * @throws `CodeService.Error` if the proposed code cannot be reserved.
         */
        reserveCode(code: CodeService.ProposedCode): Promise<void>;
        /**
         * Attempt to reserve an array of proposed codes.
         * @returns number of codes actually reserved.
         * @see the `problems` member of the `CodeService.Error` exception
         * @note If you have a set of codes to reserve, it is considerably more efficient to do them as an array rather than one at a time.
         * @throws `CodeService.Error` if any of the proposed code cannot be reserved. The details for each failed code are in the `problems` member.
         */
        reserveCodes(arg: CodeService.ReserveCodesArgs): Promise<number>;
        /**
         * Attempt to reserve the next available code for a code sequence and scope.
         */
        reserveNextAvailableCode(arg: CodeService.ReserveNextArgs): Promise<void>;
        /**
         * Attempt to reserve an array of the next available codes for a code sequence and scope.
         * The length of the array determines the number of codes requested. The values for the new codes are returned
         * in the array, so they can be associated with the supplied GUIDs.
         * @returns number of codes actually reserved.
         */
        reserveNextAvailableCodes(arg: CodeService.ReserveNextArrayArgs): Promise<number>;
        /**
         * Update the properties of a single code.
         */
        updateCode(props: CodeService.UpdatedCode): Promise<void>;
        /**
         * Update the properties of an array codes.
         * @note If you have a set of codes to update, it is considerably more efficient to do them as an array rather than one at a time.
         * @returns number of codes actually updated.
         */
        updateCodes(arg: CodeService.UpdateCodesArgs): Promise<number>;
        /** Delete an array of codes by their guids. */
        deleteCodes(guid: CodeService.CodeGuid[]): Promise<void>;
    }
    interface ReadMethods {
        /**
         * Find the next available value for the supplied `SequenceScope`.
         * If the sequence is full (there are no available values), this will throw an exception with `errorId="SequenceFull"`
         * @param from the sequence and scope to search
         * @returns the next available CodeValue in the sequence.
         */
        findNextAvailable(from: CodeService.SequenceScope): CodeService.CodeValue;
        /**
         * Find the highest currently used value for the supplied `SequenceScope`
         * @param from the sequence and scope to search
         * @returns the highest used value, or undefined if no values have been used.
         */
        findHighestUsed(from: CodeService.SequenceScope): CodeService.CodeValue | undefined;
        /** Determine whether a code is present in this CodeIndex by its Guid. */
        isCodePresent(guid: CodeService.CodeGuid): boolean;
        /** Get the data for a code in this CodeIndex by its Guid.
         * @returns the data for the code or undefined if no code is present for the supplied Guid.
         */
        getCode(guid: CodeService.CodeGuid): CodeService.CodeEntry | undefined;
        /** Look up a code by its Scope, Spec, and Value.
         * @returns the Guid of the code, or undefined if not present.
         */
        findCode(code: CodeService.ScopeSpecAndValue): CodeService.CodeGuid | undefined;
        /** Look up a code spec by its name
         * @throws if the spec is not present.
         */
        getCodeSpec(props: CodeService.CodeSpecName): CodeService.NameAndJson;
        /** Call a `CodeIteration` function for all codes in this index, optionally filtered by a `CodeFilter ` */
        forAllCodes(iter: CodeService.CodeIteration, filter?: CodeService.CodeFilter): void;
        /** Call an iteration function for all code specs in this index, optionally filtered by a `ValueFilter ` */
        forAllCodeSpecs(iter: CodeService.NameAndJsonIteration, filter?: CodeService.ValueFilter): void;
        /**
         * Verify that the Code of a to-be-inserted or to-be-updated Element:
         * 1. has already been reserved,
         * 2. if the element has a `federationGuid`, it must match the reserved value. If the federationGuid is undefined,
         * the value from the code index is returned.
         *
         * If not, throw an exception. Elements with no CodeValue are ignored.
         * @note this method is automatically called whenever elements are added or updated by a BriefcaseDb with a CodeService.
         */
        verifyCode(specName: string, arg: CodeService.ElementCodeProps): void;
    }
    type CodesDb = VersionedSqliteDb & WriteMethods & ReadMethods;
    interface InternalWriteMethods extends WriteMethods {
        /**  @internal */
        reserveFontId(props: CodeService.FontIndexProps): Promise<FontId>;
        /** @internal */
        reserveEmbeddedFaceDataId(facesKey: string): Promise<number>;
        /**  @internal */
        reserveBisCodeSpecs(specs: CodeService.BisCodeSpecIndexProps[]): Promise<void>;
    }
    interface InternalReadMethods extends ReadMethods {
        /**  @internal */
        verifyBisCodeSpec(spec: CodeService.BisCodeSpecIndexProps): void;
    }
    type InternalCodes = CodesDb & InternalWriteMethods & InternalReadMethods;
    /** @internal */
    let createForIModel: ((db: IModelDb) => Promise<CodeService>) | undefined;
    /** Register an instance of a`CodeSequence` so it can be looked up by name. */
    function registerSequence(seq: CodeSequence): void;
    /** Get a previously registered `CodeSequence` by its name.
     * @throws if no sequence by that name was registered.
     */
    function getSequence(name: string): CodeSequence;
    /**
     * Turn a `CodePops` for the briefcase of this CodeService into a `ScopeAndSpec` object for use with a CodeService.
     * This is necessary because the `spec` member of `CodeProps` refers to the id of a code spec in the iModel, and
     * the `scope` member refers to the element Id of the scope element in the iModel. This helper function
     * converts the spec Id to the spec name and looks up the `FederationGuid` of the scope element.
     */
    function makeScopeAndSpec(iModel: IModelDb, code: CodeProps): CodeService.ScopeAndSpec;
    /** Turn a `CodeProps` and  `ProposedCodeProps` into a `ProposedCode` for use with a CodeService.
     * @see [[makeScopeAndSpec]] for explanation of why this is necessary.
     */
    function makeProposedCode(arg: CodeService.MakeProposedCodeArgs): CodeService.ProposedCode;
    /** The name of a code spec */
    type CodeSpecName = string;
    /**
     * The name that identifies the "originator" of a code. Usually this is the Guid of the iModel from which a code was added,
     * but can also be used to identify a system or type from an external code service.
     */
    type CodeOriginName = string;
    /** The name that identifies the "author" of a code. Generally, this is intended to be the name of a person or group that helps identify the purpose of the code. */
    type AuthorName = string;
    /** The value for a code. */
    type CodeValue = string;
    /** The guid for a code. This identifies the real-world entity associated with the code. */
    type CodeGuid = GuidString;
    /** The guid of the scope for a code. This identifies the real-world entity that provides the uniqueness scope for code values. */
    type ScopeGuid = GuidString;
    /** An optional number associated with a code that may be used for "status" information. Values must be defined by applications. */
    type CodeState = number;
    /** The return status of an iteration function. The value "stop" causes the iteration to terminate. */
    type IterationReturn = void | "stop";
    /** An iteration function over codes in a code index. It is called with the Guid of a each code. */
    type CodeIteration = (guid: GuidString) => IterationReturn;
    /** An iteration function over code specs in a code index. It is called with the name and json of a each code spec. */
    type NameAndJsonIteration = (nameAndJson: NameAndJson) => IterationReturn;
    /** Argument for reserving an array of new codes. */
    interface ReserveCodesArgs {
        /** an array of proposed codes to reserve.
         * @note the guid of each proposed code must be supplied by the caller.
         */
        readonly codes: CodeService.ProposedCode[];
        /** If true, unless all codes are available, don't reserve any codes. Otherwise reserve all available codes. */
        readonly allOrNothing?: true;
    }
    /** Argument for reserving a code from a code sequence. */
    interface ReserveNextArgs {
        /** the properties of the new code */
        readonly code: CodeService.ProposedCodeProps;
        /** The code sequence and scope for the new code. */
        readonly from: SequenceScope;
    }
    /** Argument for reserving an array of codes from a code sequence. */
    interface ReserveNextArrayArgs {
        /** an array of proposed codes to reserve.  */
        readonly codes: CodeService.ProposedCodeProps[];
        /** The code sequence and scope for the new codes. */
        readonly from: CodeService.SequenceScope;
        /** If true, and in the event that the code sequence does not have enough available codes to fulfill all the entries in `codes`,
         * return as many as possible. Otherwise no codes are reserved. The `problems` member of the exception can be used to determine how many codes were available.
         * @note if `asManyAsPossible` is true, no error is thrown if the sequence becomes full. You must check the return value to see how many
         * were actually available. The `value` member will be undefined for any proposed codes that were not reserved.
         */
        readonly asManyAsPossible?: true;
    }
    /** Argument for updating an array of codes. */
    interface UpdateCodesArgs {
        /** Properties of the codes to update */
        readonly props: CodeService.UpdatedCode[];
        /** If true, unless all codes are updated, don't update any codes. Otherwise update all possible codes. */
        readonly allOrNothing?: true;
    }
    /** Arguments for CodeService.makeProposedCode  */
    interface MakeProposedCodeArgs {
        readonly iModel: IModelDb;
        readonly code: Required<CodeProps>;
        readonly props: CodeService.CodeGuidStateJson;
    }
    /** The properties of an Element to be checked against the code index.
     * @see CodeService.verifyCode
     */
    interface ElementCodeProps {
        /** iModel from which the code is being inserted/updated. */
        readonly iModel: IModelDb;
        /** Properties of the code */
        readonly props: {
            /** The imodel-specific code properties. */
            readonly code: CodeProps;
            /**
             * The federationGuid of the element being inserted or updated.
             * If federationGuid is defined, it is must match the value in the code index or an error is thrown.
             * If it is undefined, the value from the code index is returned here.
             */
            federationGuid?: GuidString;
        };
    }
    /** a name and a json object. Used for code specs, authors and origins. */
    interface NameAndJson {
        readonly name: string;
        readonly json?: SettingsContainer;
    }
    /** A code Scope guid, and code spec name. */
    interface ScopeAndSpec {
        readonly specName: CodeSpecName;
        readonly scopeGuid: ScopeGuid;
    }
    /** A code Scope guid, code spec, and code value. */
    interface ScopeSpecAndValue extends ScopeAndSpec {
        readonly value: CodeValue;
    }
    /** The data held in a code index for a single code. */
    interface CodeEntry {
        /** The name of the code spec for this code. */
        readonly specName: CodeSpecName;
        /** The guid of the entity that provides the scope for this code. */
        readonly scopeGuid: ScopeGuid;
        /** The value of this code. */
        readonly value: CodeValue;
        /** The guid of the entity this code identifies. */
        readonly guid: CodeGuid;
        /** the state of the code. May be undefined. */
        readonly state?: CodeState;
        /** The name of the originating source of this code (usually an iModel Guid). May be undefined. */
        readonly origin: CodeOriginName;
        /** The name of the author of this code. May be undefined. */
        readonly author?: AuthorName;
        /** Option json properties associated with this code. May be undefined. */
        readonly json?: SettingsContainer;
    }
    /** A filter used to limit and/or sort the values returned by an iteration. */
    interface ValueFilter {
        /** A value filter. May include wild cards when used with `GLOB` or `LIKE` */
        readonly value?: string;
        /** The comparison operator for `value`. Default is `=` */
        readonly valueCompare?: "GLOB" | "LIKE" | "NOT GLOB" | "NOT LIKE" | "=" | "<" | ">";
        /** Order results ascending or descending. If not supplied, the results are unordered (random). */
        readonly orderBy?: "ASC" | "DESC";
        /** An SQL expression to further filter results. This string is appended to the `WHERE` clause with an `AND` (that should not be part of the sqlExpression) */
        readonly sqlExpression?: string;
    }
    /** A filter to limit and/or sort the values for the [[CodeIndex.forAllCodes]] iteration. */
    interface CodeFilter extends ValueFilter {
        /** If supplied, limit results to only those with this spec */
        readonly specName?: CodeSpecName;
        /** If supplied, limit results to only those with this scope Guid */
        readonly scopeGuid?: ScopeGuid;
        /** If supplied, limit results to only those with this origin */
        readonly origin?: CodeOriginName;
    }
    /** Author and origin information supplied when codes are reserved. */
    interface AuthorAndOrigin {
        /** The name of the individual or group for whom the code was reserved. */
        readonly author: Mutable<NameAndJson>;
        /** The identity of the "originator" of the code. This is usually a guid of an iModel, but can be any unique string. */
        readonly origin: Mutable<NameAndJson>;
    }
    /** The Guid, state, and json properties of a code. */
    interface CodeGuidStateJson {
        /** The Guid of the new code. This must be always be supplied by the application. */
        readonly guid: CodeGuid;
        /** An optional value for the state of the code. */
        readonly state?: CodeState;
        /** An optional json object to be stored with the code. */
        readonly json?: SettingsContainer;
    }
    /** Properties of a "proposed" new code to be reserved.
     * @note the Guid of the entity identified by this code *must* be supplied, but `value` is optional, since
     * this may be used to reserve codes from a sequence where the value is generated.
     */
    interface ProposedCodeProps extends CodeGuidStateJson {
        /** The value for the proposed code.
         * @note For code sequence operations, this value is ignored on input and is set with a new value from the sequence on successful return.
         */
        value?: CodeValue;
    }
    /** Properties of a proposed new code that is not from a code sequence (its `value` is required). */
    type ProposedCode = ProposedCodeProps & ScopeSpecAndValue;
    /** Properties that describe a code sequence and a scope and spec for a proposed code or array of codes from a sequence. */
    interface SequenceScope extends ScopeAndSpec {
        /** The code sequence. */
        readonly seq: CodeSequence;
        /** A valid current value. If supplied, the returned value will always be later in the sequence than this. */
        readonly start?: CodeValue;
    }
    /** Properties of a code to be updated.
     * @note The `guid` member identifies the code to be updated and is required.
     * All other properties are optional - if `undefined`, its value is not changed.
     */
    type UpdatedCode = MarkRequired<Partial<ProposedCode>, "guid">;
    /** A proposed code that could not be reserved due to some error. */
    interface ReserveProblem {
        /** the proposed code that failed. */
        readonly code: ProposedCode;
        /** the reason for the failure */
        readonly errorId: ErrorId;
        /** the error message from the exception for this proposed code. */
        readonly message: string;
    }
    /** A update to a code that failed for some error. */
    interface UpdateProblem {
        /** The properties of the code that was to be updated */
        readonly prop: UpdatedCode;
        /** the reason for the failure */
        readonly errorId: ErrorId;
        /** the error message from the exception for the update request. */
        readonly message: string;
    }
    /**
     * A sequence of code values following a increasing pattern. Valid code sequences must have a first value, a last value, and
     * a way to get the next valid value from an existing valid value.
     * Code sequences have a `sequenceName` so they can be registered using `CodeService.registerSequence`.
     */
    interface CodeSequence {
        /** the name of this CodeSequence. */
        get sequenceName(): string;
        /** Get the first valid value for this CodeSequence */
        getFirstValue(): CodeValue;
        /** Get the last valid value for this CodeSequence */
        getLastValue(): CodeValue;
        /** Get the next valid value for this CodeSequence from the supplied value.
         * If the sequence is full (that is, the next value is greater than the last value, this method should throw with errorId="SequenceFull".
         * @return the next valid value according to the rules of this CodeSequence.
         */
        getNextValue(code: CodeValue): CodeValue;
        /** Determine whether this supplied value is valid for this sequence. */
        isValidCode(code: CodeValue): boolean;
    }
    /** @internal */
    interface FontIndexProps {
        id?: number;
        fontType: FontType;
        fontName: string;
    }
    /** @internal */
    interface BisCodeSpecIndexProps {
        id?: number;
        name: string;
        props: string;
    }
    /** Exception class thrown by `CodeService` methods. */
    class Error extends BentleyError {
        /** A string that indicates the type of problem that caused the exception. */
        readonly errorId: ErrorId;
        /** For [[CodeService.reserveCodes]] and [[CodeService.updateCodes]], a list of the problem details. */
        readonly problems?: ReserveProblem[] | UpdateProblem[];
        /** @internal */
        constructor(errorId: ErrorId, errNum: number, message: string, problems?: ReserveProblem[] | UpdateProblem[]);
    }
    /** Identifiers for exceptions thrown by `CodeService` methods.
     * @see [[CodeService.Error.errorId]]
     */
    type ErrorId = "BadIndexProps" | "CorruptIModel" | "CorruptIndex" | "DuplicateValue" | "GuidIsInUse" | "GuidMismatch" | "IllegalValue" | "InconsistentIModels" | "IndexReadonly" | "InvalidCodeScope" | "InvalidGuid" | "InvalidSequence" | "MissingCode" | "MissingGuid" | "MissingInput" | "MissingSpec" | "NoCodeIndex" | "NotAuthorized" | "SequenceFull" | "ReserveErrors" | "SequenceNotFound" | "SqlLogicError" | "UpdateErrors" | "ValueIsInUse" | "WrongVersion";
}
//# sourceMappingURL=CodeService.d.ts.map