/// <reference types="node" />
import { Decoder } from '@iotize/common/converter/api';
import { DEFAULT_SCRAM_SALT_GENERATOR, Tap, TapConfigurator } from '@iotize/device-client.js';
import { ResponseInterface } from '@iotize/device-client.js/client/api';
import { Acl, AnonymousProfile, ApplicationOption, BundleConfig, CloudConfig, DataConfig, MemoryVariableConfig, MqttRelayConfig, ProfileConfig, SemanticVersion, SpecialFeature as SpecialFeatureConfig, SpecialProfileConfig, TapConfigSchema, TapOptions, TargetConfig, UserConfig } from '@iotize/device-client.js/config/schema/v1';
import * as Ajv from 'ajv';
import { Observable, Subject } from 'rxjs';
import { InvalidTapConfig } from './definitions';
import { ProtocolConfigurationDataConfigConverter } from './device-client-extension';
import { TapAppPathConverter } from './tap-app-path-converter';
export declare function bytesToUtf8(input: Uint8Array): string;
export declare class InvalidTapSchemaConfig extends InvalidTapConfig {
    validate: Ajv.ValidateFunction;
    errors: Ajv.ErrorObject[];
    constructor(validate: Ajv.ValidateFunction);
    static errorsToString(errors: Ajv.ErrorObject[] | undefined | null): string;
}
export declare function semanticVersionStringToInt(version: string | number): number;
export declare function parseTapConfig(fileContent: string | Buffer): TapConfigSchema;
export declare function isJsonString(str: string): boolean;
export declare function fromXml(fileContent: string): TapConfigSchema;
/**
 * Validate schema. Throw error if schema is not valid
 * @throws @{link InvalidTapSchemaConfig}
 * @param config the tap config object
 * @param schemas optial schema used for validation. If not provided, default one will be used
 *
 * @returns validator function
 */
export declare function validateTapConfig(config: Object, schemas?: Object[]): Ajv.ValidateFunction;
export declare function checkErrors(config: Object): Ajv.ErrorObject[];
export declare namespace SchemaTapConfigurator {
    interface Event {
        type: string;
        message: string;
        payload?: any;
    }
    interface Options {
        delayMs: number;
    }
}
/**
 * Configure tap from a configuration file schema
 *
 * JSON schema definition is here: TODO
 *
 * TODO:
 *  - Improve apply config with more comprehensive errors (add configuration that failed)
 *
 */
export declare class SchemaTapConfigurator implements TapConfigurator<SchemaTapConfigurator.Event> {
    /**
     * Schema config to write
     */
    private _schema;
    options: SchemaTapConfigurator.Options;
    bundleConfigurator: MemoryBundleConfigurator;
    protocolConfDataConverter: ProtocolConfigurationDataConfigConverter;
    appPathConverter: TapAppPathConverter;
    /**
     *
     */
    tap: Tap;
    _writeSubject: Subject<SchemaTapConfigurator.Event>;
    _readSubject: Subject<SchemaTapConfigurator.Event>;
    private _tmpConfig;
    scramSaltGenerator: typeof DEFAULT_SCRAM_SALT_GENERATOR;
    constructor(
    /**
     * Schema config to write
     */
    _schema: TapConfigSchema, options?: SchemaTapConfigurator.Options, bundleConfigurator?: MemoryBundleConfigurator, protocolConfDataConverter?: ProtocolConfigurationDataConfigConverter, appPathConverter?: TapAppPathConverter);
    get schema(): TapConfigSchema;
    configure(tap: Tap): Observable<SchemaTapConfigurator.Event>;
    private _configure;
    read(tap: Tap): Observable<SchemaTapConfigurator.Event>;
    _read(): Promise<void>;
    setupConfigState(): Promise<void>;
    isConfigured(): Promise<boolean>;
    applyConfig(newVersion?: number | SemanticVersion): Promise<void>;
    sleep(delayMs: number): Promise<void>;
    private _useScram;
    _writeConfig(): Promise<void>;
    _writeData(data: DataConfig): Promise<void>;
    _readData(): Promise<DataConfig>;
    _readProfiles(): Promise<ProfileConfig[]>;
    _getGroupName(profileId: number): Promise<string>;
    private readSchema;
    _readTarget(): Promise<Partial<TargetConfig>>;
    _writeTarget(target: TargetConfig): Promise<void>;
    _successfullCall(call: Promise<ResponseInterface<void>>): Promise<void>;
    _apiCall(call: Promise<ResponseInterface<void>>): Promise<ResponseInterface<void>>;
    _readTap(): Promise<TapOptions>;
    _writeTap(tapOptions: TapOptions): Promise<void>;
    _readMqttRelay(): Promise<MqttRelayConfig>;
    _writeMqttRelay(options: MqttRelayConfig): Promise<void>;
    private _writeCall;
    _readCloudOptions(): Promise<CloudConfig>;
    _writeCloudOptions(options: CloudConfig): Promise<void>;
    _writeCallOptional(call: Promise<ResponseInterface<void>>): Promise<ResponseInterface<void>>;
    _readApplication(): Promise<ApplicationOption>;
    _writeApplication(application: ApplicationOption): Promise<void>;
    _writeUser(user: UserConfig | SpecialProfileConfig | AnonymousProfile, parentGroup?: ProfileConfig | SpecialProfileConfig | AnonymousProfile): Promise<void>;
    /**
     * TODO inprove with user key check...
     * @param userId
     * @param hexString
     */
    private _writeUserKey;
    _writeUserPassword(userId: number, password: string, salt: number | undefined): Promise<void>;
    _writeProfile(group: ProfileConfig | SpecialProfileConfig | AnonymousProfile): Promise<void>;
    _writeBundle(bundle: BundleConfig): Promise<void>;
    get profiles(): (UserConfig | SpecialProfileConfig | AnonymousProfile)[];
    getProfileByName(profileName: string): ProfileConfig | SpecialProfileConfig | AnonymousProfile;
    _readBundles(): Promise<BundleConfig[]>;
    _listBundles(): Promise<number[]>;
    private _listBundlesFromProfile;
    _readUserProfile(groupId: number): Promise<ProfileConfig>;
    _readBundle(bundleId: number): Promise<BundleConfig>;
    _readAcls(bundleId: number): Promise<Record<string, Acl>>;
    _readAcl(profileName: string, bundleId: number): Promise<Acl>;
    _readSpecialFeatures(): Promise<Record<number, SpecialFeatureConfig[]>>;
    _listProfiles(): Promise<number[]>;
    private errorHandler;
    private _next;
}
export declare namespace SchemaTapConfigurator {
    class MyError extends Error {
        code: ErrorCode;
        cause: Error;
        constructor(code: ErrorCode, cause: Error);
    }
    enum ErrorCode {
        ReadVariableType = 0
    }
    interface ConfiguratorPart<T, T2, T3 = undefined> {
        read(tap: Tap, readOptions: T2): Promise<T>;
        write(tap: Tap, data: T, writeOptions: T3): Promise<void>;
        writeEvents?: Subject<SchemaTapConfigurator.Event>;
    }
}
export declare class MemoryBundleConfigurator implements SchemaTapConfigurator.ConfiguratorPart<BundleConfig, {
    bundleId: number;
}, {
    bundleId: number;
}> {
    variableConfigurator: VariableConfigurator;
    private _writeSubject?;
    get writeEvents(): Subject<SchemaTapConfigurator.Event>;
    constructor(variableConfigurator?: VariableConfigurator);
    read(tap: Tap, readOptions: {
        bundleId: number;
        readVariables: boolean;
    }): Promise<BundleConfig>;
    private _readVariables;
    private _readVariable;
    private _listVariablesForBundle;
    write(tap: Tap, bundle: BundleConfig, writeOptions: {
        bundleId: number;
    }): Promise<void>;
    private _writeVariable;
    private _next;
}
export declare class VariableConfigurator implements SchemaTapConfigurator.ConfiguratorPart<MemoryVariableConfig, {
    variableId: number;
}, {
    bundleId: number;
}> {
    stringConverter: Decoder<Uint8Array, string>;
    constructor(stringConverter?: Decoder<Uint8Array, string>);
    read(tap: Tap, readOptions: {
        variableId: number;
    }): Promise<MemoryVariableConfig>;
    write(tap: Tap, variable: MemoryVariableConfig, writeOptions: {
        bundleId: number;
    }): Promise<void>;
    private _encodeVariableMetaData;
    private _decodeMetaData;
    private readVariableAddress;
    private readVariableType;
    private errorHandler;
    private _writeCall;
}
