/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
 */

import { Injectable } from '@angular/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';

@Plugin({
    pluginName: 'AGCCloudDBPlugin',
    plugin: 'cordova-plugin-agc-clouddb',
    pluginRef: 'AGCCloudDBPlugin',
    platforms: ['Android', 'iOS']
})
@Injectable()
export class AGCCloudDBPlugin extends IonicNativePlugin {
    /**
     * Initializes AGConnectCloudDB.
     */
    @Cordova({ otherPromise: true })
    initialize(): Promise<void> {
        return;
    }

    /**
     * This method is called to create or modify an object type, 
     * define a set of CloudDBZoneObject storage objects, 
     * and store data generated by the application.
     */
    @Cordova({ otherPromise: true })
    createObjectType(): Promise<void> {
        return;
    }

    /**
     * Obtains all CloudDBZoneConfig lists in the AGConnectCloudDB instance on the device.
     * @returns CloudDBZoneConfig object and configure Cloud DB zone information 
     * such as the synchronization property, access property, encrypted storage property, 
     * and data persistency property.
     */
    @Cordova({ otherPromise: true })
    getCloudDBZoneConfigs(): Promise<CloudDBZoneConfig[]> {
        return;
    }

    /**
     * Asynchronously creates or opens an object of a Cloud DB zone which represents a unique data storage zone.
     * @param config The callback to execute when the Promise is rejected.
     * @param isAllowToCreate Specifies whether to allow Cloud DB zone object creation.
     * @returns Cloud DB zone object. Developers can use this object to add, delete, modify, query, and listen on data.
     */
    @Cordova({ otherPromise: true })
    openCloudDBZone2(config: CloudDBZoneConfig, isAllowToCreate: boolean): Promise<AGCCloudDBZone> {
        return;
    }

    /**
     * Asynchronously creates or opens an object of a Cloud DB zone which represents a unique data storage zone.
     * @param config The callback to execute when the Promise is rejected.
     * @param isAllowToCreate Specifies whether to allow Cloud DB zone object creation.
     * @returns Cloud DB zone object. Developers can use this object to add, delete, modify, query, and listen on data.
     */
    @Cordova({ otherPromise: true })
    openCloudDBZone(config: CloudDBZoneConfig, isAllowToCreate: boolean): Promise<AGCCloudDBZone> {
        return;
    }

    /**
     * Listens to registered user key change events.
     * @param callback Callback function to be called when listener is triggered.
     */
    @Cordova({ otherPromise: true })
    addEventListener(callback: (eventType: AGCCloudDBEventType) => void): Promise<void> {
        return;
    }

    /**
     * Registers a listener for data key changes.
     * @param needFetchDataEncryptionKey Checks whether to update the data key. 
     * If the value is true: update is required,  the value is false: update is not required.
     * @param callback The callback to execute when the Promise is rejected.
     */
    @Cordova({ otherPromise: true })
    addDataEncryptionKeyListener(needFetchDataEncryptionKey: boolean, callback: (isDataKeyChange: boolean) => void): Promise<void> {
        return;
    }

    /**
     * Deletes the Cloud DB zone object that is no longer used on the device.
     * @param zoneName The callback to execute when the Promise is rejected.
     */
    @Cordova({ otherPromise: true })
    deleteCloudDBZone(zoneName: string): Promise<void> {
        return;
    }

    /**
     * Closes the Cloud DB zone object opened on the device.
     * @param id An id of Cloud DB zone to be closed.
     */
    @Cordova({ otherPromise: true })
    closeCloudDBZone(id: string): Promise<void> {
        return;
    }

    /**
     * Enables data synchronization between the device and cloud.
     * @param zoneName Cloud DB zone name
     */
    @Cordova({ otherPromise: true })
    enableNetwork(zoneName: string): Promise<void> {
        return;
    }

    /**
     * Disables data synchronization between the device and cloud.
     * @param zoneName Cloud DB zone name
     */
    @Cordova({ otherPromise: true })
    disableNetwork(zoneName: string): Promise<void> {
        return;
    }

    /**
     * A data key used to encrypt user data, which is automatically generated by the system. 
     * To prevent from being cracked when using one key for a long time, 
     * you can call this method to update the data key.
     * @returns True if operation successful, otherwise false.
     */
    @Cordova({ otherPromise: true })
    updateDataEncryptionKey(): Promise<boolean> {
        return;
    }

    /**
     * Sets or modifies the user password for Cloud DB full encryption.
     * @param userKey User password.
     * @param userReKey New user password.
     * @returns True if operation successful, otherwise false.
     */
    @Cordova({ otherPromise: true })
    setUserKey(userKey: string, userReKey: string): Promise<boolean> {
        return;
    }

}

export class AGCCloudDBQuery {
    private readonly query: QueryObject;

    private constructor(className: string) {
        this.query = {
            className: className,
            queryElements: [],
        }
    }

    /**
     * Obtains a AGCCloudDBQuery object and specifies the object type to be queried. 
     * The AGCCloudDBQuery object does not provide any construction method. 
     * You can obtain an object type instance only by using the where method.
     * @param className Cloud DB zone name
     */
    static where(className: string) {
        return new AGCCloudDBQuery(className);
    }

    /**
     * Adds a query condition where the value of a field in an entity class 
     * is equal to a specified value.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    equalTo(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.EQUAL_TO,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field in an entity class 
     * is not equal to a specified value.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    notEqualTo(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.NOT_EQUAL_TO,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field in an entity class 
     * is greater than a specified value.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    greaterThan(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.GREATER_THAN,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field in an entity class 
     * is greater than or equal to a specified value.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    greaterThanOrEqualTo(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.GREATER_THAN_OR_EQUAL_TO,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field in an entity class 
     * is less than a specified value.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    lessThan(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.LESS_THAN,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field in an entity class 
     * is less than or equal to a specified value.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    lessThanOrEqualTo(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.LESS_THAN_OR_EQUAL_TO,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field in an entity class 
     * is contained in a specified array.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    in(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.IN,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field of the string or 
     * text type in an entity class starts with a specified substring.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    beginsWith(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.BEGINS_WITH,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field of the string or 
     * text type in an entity class ends with a specified substring.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    endsWith(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.ENDS_WITH,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where the value of a field of the string 
     * or text type in an entity class contains a specified substring.
     * @param fieldName Name of a field in an entity class.
     * @param value Specified value of the selected field. 
     * The data type of the value must be the same as that of the selected field value. 
     * Otherwise, an exception is thrown.
     */
    contains(fieldName: string, value: any) {
        this.query.queryElements.push({
            operation: QueryOperation.CONTAINS,
            fieldName: fieldName,
            value: value,
        })
        return this
    }

    /**
     * Adds a query condition where a field in an entity class is null.
     * @param fieldName Name of a field in an entity class.
     */
    isNull(fieldName: string) {
        this.query.queryElements.push({
            operation: QueryOperation.IS_NULL,
            fieldName: fieldName,
        })
        return this
    }

    /**
     * Adds a query condition where a field in an entity class is not null.
     * @param fieldName Name of a field in an entity class.
     */
    isNotNull(fieldName: string) {
        this.query.queryElements.push({
            operation: QueryOperation.IS_NOT_NULL,
            fieldName: fieldName,
        })
        return this
    }

    /**
     * Sorts the query results in ascending order by a specified field.
     * @param fieldName Name of a field in an entity class.
     */
    orderByAsc(fieldName: string) {
        this.query.queryElements.push({
            operation: QueryOperation.ORDER_BY_ASC,
            fieldName: fieldName,
        })
        return this
    }

    /**
     * Sorts the query results in descending order by a specified field.
     * @param fieldName Name of a field in an entity class.
     */
    orderByDesc(fieldName: string) {
        this.query.queryElements.push({
            operation: QueryOperation.ORDER_BY_DESC,
            fieldName: fieldName,
        })
        return this
    }

    /**
     * Add query conditions to specify the number of 
     * data records in the returned query result set.
     * @param count Maximum number of data records that can be obtained.
     * @param offset Specifies the start position of data records. 
     * You can specify whether to set the offset position based on the actual requirements.
     */
    limit(count: any, offset?: number) {
        if (offset) {
            this.query.queryElements.push({
                operation: QueryOperation.LIMIT_CONDITION,
                value: count,
                offset: offset
            })
            return this
        } else {
            this.query.queryElements.push({
                operation: QueryOperation.LIMIT_CONDITION,
                value: count,
            })
            return this
        }
    }

    /**
     * Set the start position of the data to be queried, and return to 
     * the data records with the corresponding records at the start position included.
     * @param object The object corresponding to the start position.
     */
    startAt(object: any) {
        this.query.queryElements.push({
            operation: QueryOperation.START_AT,
            value: object
        })
        return this
    }

    /**
     * Set the start position of the data to be queried, and return to 
     * the data records with the corresponding records at the start position not included.
     * @param object The object corresponding to the start position.
     */
    startAfter(object: any) {
        this.query.queryElements.push({
            operation: QueryOperation.START_AFTER,
            value: object
        })
        return this
    }

    /**
     * Set the end position of the data to be queried, and return to 
     * the data records with the corresponding records at the end position included.
     * @param object The object corresponding to the start position.
     */
    endAt(object: any) {
        this.query.queryElements.push({
            operation: QueryOperation.END_AT,
            value: object
        })
        return this
    }

    /**
     * Set the end position of the data to be queried, and return to 
     * the data records with the corresponding records at the end position not included.
     * @param object The object corresponding to the start position.
     */
    endBefore(object: any) {
        this.query.queryElements.push({
            operation: QueryOperation.END_BEFORE,
            value: object
        })
        return this
    }

    /**
     * This method is used to build the query. 
     * This method has to be called after query chain has been completed.
     */
    build() {
        Object.freeze(this);
        return this.query;
    }
}

export class AGCCloudDBTransaction {
    private readonly transactions: Transaction[];
    private constructor() {
        this.transactions = [];
    }

    /**
     * Initializes an AGCCloudDBTransaction object.
     * @param zoneName Cloud DB zone name
     */
    static function() {
        return new AGCCloudDBTransaction();
    }

    /**
     * Writes a group of objects to the Cloud DB zone in a transaction in batches.
     * @param className A class object that represents the object type entity class defined by the developer.
     * @param data A list, represents the data to be written.
     */
    executeUpsert(className: string, data: any[]) {
        this.transactions.push({
            operation: Operation.UPSERT,
            className: className,
            data: data
        })
        return this
    }

    /**
     * Deletes a group of objects from the Cloud DB zone in a transaction in batches.
     * @param className A class object that represents the object type entity class defined by the developer.
     * @param data A list, represents the data to be deleted.
     */
    executeDelete(className: string, data: any[]) {
        this.transactions.push({
            operation: Operation.DELETE,
            className: className,
            data: data
        })
        return this
    }

    /**
     * Queries a set of objects that meet specific conditions from the Cloud DB zone on the cloud in a transaction.
     * @param className A class object that represents the object type entity class defined by the developer.
     * @param data A QueryObject object, which indicates the query condition.
     */
    executeQuery(className: string, data: QueryObject) {
        this.transactions.push({
            operation: Operation.QUERY,
            className: className,
            data: data
        })
        return this
    }

    /**
     * This method is used to build the Transaction list.
     * @returns Transaction list.
     */
    build() {
        Object.freeze(this);
        return this.transactions;
    }
}
export class AGCCloudDBZone {
    private readonly _id: string;

    private constructor(id: string) {
        this._id = id;
    }

    /**
     * Obtains the id of current Cloud DB zone instance.
     */
    get id(): string {
        return this._id;
    }

    /**
     * Obtains the current configuration information of Cloud DB zone.
     * @returns A CloudDBZoneConfig object.
     */
    @Cordova({ otherPromise: true })
    getCloudDBZoneConfig(): Promise<CloudDBZoneConfig> {
        return;
    }

    /**
     * Writes a group of objects to the current Cloud DB zone in batches.
     * @param className Name of the object type.
     * @param cloudDBZoneObjectArray Object datas to be written.
     * @returns Number of objects that are successfully written.
     */
    @Cordova({ otherPromise: true })
    executeUpsert(className: string, cloudDBZoneObjectArray: any[]): Promise<number> {
        return;
    }

    /**
     * Deletes a group of Cloud DB zone objects whose primary key values are the same as those of the input object list in batches.
     * @param className Name of the object type.
     * @param cloudDBZoneObjectArray Object datas to be deleted.
     * @returns Number of objects that are successfully deleted.
     */
    @Cordova({ otherPromise: true })
    executeDelete(className: string, cloudDBZoneObjectArray: any[]): Promise<number> {
        return;
    }

    /**
     * Queries objects that meet specified conditions in Cloud DB zone and encapsulates the query result set into a CloudDBZoneSnapshot.
     * @param queryObject A QueryObject object, which indicates the query condition.
     * @param queryPolicy Query policy, which specifies the data source to be queried.
     * @returns CloudDBZoneSnapshot object that encapsulates the query result set.
     */
    @Cordova({ otherPromise: true })
    executeQuery(queryObject: QueryObject, queryPolicy: CloudDBZoneQueryPolicy): Promise<CloudDBZoneSnapshot> {
        return;
    }

    /**
     * Queries objects that meet specified conditions in Cloud DB zone and returns the average value of specified fields.
     * @param queryObject A QueryObject object, which indicates the query condition.
     * @param fieldName Specifies the name of the fields whose average value needs to be calculated in the query object.
     * @param queryPolicy Query policy, which specifies the data source to be queried.
     * @returns The avarage value.
     */
    @Cordova({ otherPromise: true })
    executeAverageQuery(queryObject: QueryObject, fieldName: string, queryPolicy: CloudDBZoneQueryPolicy): Promise<string> {
        return;
    }

    /**
     * Queries objects that meet specific conditions and returns the sum of data record values of specified fields in the Cloud DB zone.
     * @param queryObject A QueryObject object, which indicates the query condition.
     * @param fieldName Specifies the name of the fields whose sum value needs to be calculated in the query object.
     * @param queryPolicy Query policy, which specifies the data source to be queried.
     * @returns The sum result.
     */
    @Cordova({ otherPromise: true })
    executeSumQuery(queryObject: QueryObject, fieldName: string, queryPolicy: CloudDBZoneQueryPolicy): Promise<string> {
        return;
    }

    /**
     * Queries the objects that meet specific conditions and returns the maximum value of the data records in the specified fields in the Cloud DB zone.
     * @param queryObject A QueryObject object, which indicates the query condition.
     * @param fieldName Specifies the name of the fields whose max value needs to be calculated in the query object.
     * @param queryPolicy Query policy, which specifies the data source to be queried.
     * @returns The maximum value.
     */
    @Cordova({ otherPromise: true })
    executeMaximumQuery(queryObject: QueryObject, fieldName: string, queryPolicy: CloudDBZoneQueryPolicy): Promise<string> {
        return;
    }

    /**
     * Queries the objects that meet specific conditions in the Cloud DB zone and returns the minimum value of the data records in the designated fields.
     * @param queryObject A QueryObject object, which indicates the query condition.
     * @param fieldName Specifies the name of the fields whose min value needs to be calculated in the query object.
     * @param queryPolicy Query policy, which specifies the data source to be queried.
     * @returns The minimum value.
     */
    @Cordova({ otherPromise: true })
    executeMinimalQuery(queryObject: QueryObject, fieldName: string, queryPolicy: CloudDBZoneQueryPolicy): Promise<string> {
        return;
    }

    /**
     * Queries the objects that meet specific conditions in the Cloud DB zone and returns the number of data records of the specified fields.
     * @param queryObject A QueryObject object, which indicates the query condition.
     * @param fieldName Specifies the name of the fields whose count value needs to be calculated in the query object.
     * @param queryPolicy Query policy, which specifies the data source to be queried.
     * @returns The number of data result.
     */
    @Cordova({ otherPromise: true })
    executeCountQuery(queryObject: QueryObject, fieldName: string, queryPolicy: CloudDBZoneQueryPolicy): Promise<string> {
        return;
    }

    /**
     * Queries all object data that meets specified conditions in Cloud DB but has not been synchronized to the cloud, and encapsulates the query result set into a CloudDBZoneSnapshot.
     * @param queryObject A QueryObject object, which indicates the query condition.
     * @returns CloudDBZoneSnapshot object that encapsulates the query result set.
     */
    @Cordova({ otherPromise: true })
    executeQueryUnsynced(queryObject: QueryObject): Promise<CloudDBZoneSnapshot> {
        return;
    }

    /**
     * Executes a specified transaction operation.
     * @param transactions You can encapsulate a group of operations in the array, 
     * and then use this interface to implement the functions of adding, deleting, modifying, 
     * and querying operations in a transaction.
     * @returns An object, which encapsulates the execution status, result, 
     * and exception information of runTransaction(). 
     * For example, you can call the isSuccessful property based on this 
     * object to check whether the query operation is successful.
     */
    @Cordova({ otherPromise: true })
    runTransaction(transactions: Transaction[]): Promise<TransactionResult> {
        return;
    }

    /**
     * Registers a listener for a specified object on the device or cloud. 
     * When the data of the object that is listened on is changed, the registered onSnapshotUpdate event is triggered.
     * @param queryObject A QueryObject object, which indicates the query condition.
     * @param queryPolicy Query policy, which specifies the data source to be queried.
     * @param callback Callback function to be called when listener is triggered.
     * @returns A ListenerHandler object that remains valid until the remove() method 
     * of the ListenerHandler class is explicitly called by the developer.
     */
    @Cordova({ otherPromise: true })
    async subscribeSnapshot(queryObject: QueryObject, queryPolicy: CloudDBZoneQueryPolicy, callback: (cloudDBZoneSnapshot: CloudDBZoneSubscribeSnapshot) => void): Promise<ListenerHandler> {
        return;
    }
}

export class ListenerHandler {
    private readonly zoneId: string;
    private readonly listenerId: string;

    private constructor(zoneId: string, listenerId: string) {
        this.zoneId = zoneId;
        this.listenerId = listenerId;
    }

    /**
     * Deregisters the snapshot listener.
     */
    @Cordova({ otherPromise: true })
    remove(): Promise<void> {
        return;
    }
}

/**
 * Exception base interface of Cloud DB, which is inherited from AGCException. 
 * AGConnectCloudDBException provides methods for developers to obtain exception information, 
 * including error codes and detailed error information.
 * @param message An error information.
 * @param code An error code.
 */
export interface AGCCloudDBException {
    message: string,
    code: number
}
/**
 * Transaction interface describes a transaction. 
 * The transaction provides the query, upsert, and delete methods to add, 
 * delete, modify, and query data in the Cloud DB zone on the cloud.
 */
export interface Transaction {
    className: string,
    operation: Operation,
    data: any[] | QueryObject
}

/**
 * This interface defines result object from the runTransaction() method. 
 * If the transaction array contains a query, than result of query will be 
 * returned on queryResult field, otherwise this field will be empty.
 */
export interface TransactionResult {
    isSuccessful: boolean,
    queryResult: {}
}

/**
 * This interface is used to create a CloudDBZoneConfig object and configure 
 * Cloud DB zone information such as the synchronization property, 
 * access property, encrypted storage property, and data persistency property.
 */
export interface CloudDBZoneConfig {
    cloudDBZoneName: string,
    accessProperty: CloudDBZoneAccessProperty,
    syncProperty: CloudDBZoneSyncProperty,
    capacity?: number,
    persistenceEnabled?: boolean,
    isEncrypted: boolean,
    key?: string,
    reKey?: string
}

/**
 * This interface defines object type which on the query will be executed and query conditions.
 */
export interface QueryObject {
    className: string,
    queryElements: QueryElement[]
}

/**
 * This interface defines a single query condition.
 */
export interface QueryElement {
    operation: QueryOperation,
    fieldName?: string,
    offset?: number,
    value?: any
}

/**
 * CloudDBZoneSnapshot interface is used to describe the queried snapshot data, 
 * including full object sets, added and modified object sets, and newly deleted object sets.
 */
export interface CloudDBZoneSnapshotData {
    hasPendingWrites: boolean,
    isFromCloud: boolean,
    snapshotObjects: any[],
    upsertedObjects: any[],
    deletedObjects: any[]
}

/**
 * CloudDBZoneSnapshot interface is used to including full object sets, 
 * added and modified object sets, and newly deleted object sets.
 */
export interface CloudDBZoneSnapshot extends CloudDBZoneSnapshotData {
}

/**
 * CloudDBZoneSnapshot interface is used to describe the queried snapshot data.
 */
export interface CloudDBZoneSubscribeSnapshot {
    id: string,
    data?: CloudDBZoneSnapshotData,
    error?: AGCCloudDBException
}

/**
 * These enum values provides various predicates such as 
 * contains, equalTo, notEqualTo, and in to construct query conditions.
 */
export enum QueryOperation {
    LIMIT_CONDITION = "limit",
    START_AT = "startAt",
    START_AFTER = "startAfter",
    END_AT = "endAt",
    END_BEFORE = "endBefore",
    EQUAL_TO = "equalTo",
    NOT_EQUAL_TO = "notEqualTo",
    GREATER_THAN = "greaterThan",
    GREATER_THAN_OR_EQUAL_TO = "greaterThanOrEqualTo",
    LESS_THAN = "lessThan",
    LESS_THAN_OR_EQUAL_TO = "lessThanOrEqualTo",
    BEGINS_WITH = "beginsWith",
    ENDS_WITH = "endsWith",
    CONTAINS = "contains",
    IS_NULL = "isNull",
    IS_NOT_NULL = "isNotNull",
    ORDER_BY_ASC = "orderByAsc",
    ORDER_BY_DESC = "orderByDesc",
    IN = "in"
}

/**
 * These enum values provides which operation is going to be performed.
 */
export enum Operation {
    UPSERT = "upsert",
    DELETE = "delete",
    QUERY = "query"
}

/**
 * Synchronization property of the Cloud DB zone, 
 * which specifies whether to synchronize data of Cloud DB zone between 
 * the device and the cloud and the synchronization mode.
 */
export enum CloudDBZoneSyncProperty {
    CLOUDDBZONE_LOCAL_ONLY = 0,
    CLOUDDBZONE_CLOUD_CACHE = 1
}

/**
 * Access property of the Cloud DB zone, 
 * which is used to define the security property when an application accesses Cloud DB zone.
 */
export enum CloudDBZoneAccessProperty {
    CLOUDDBZONE_PUBLIC = 0
}

/**
 * Query policy, which specifies the data source to be queried.
 */
export enum CloudDBZoneQueryPolicy {
    POLICY_QUERY_FROM_LOCAL_ONLY = 1,
    POLICY_QUERY_FROM_CLOUD_ONLY = 2,
    POLICY_QUERY_DEFAULT = 3
}

/**
 * Type of the change event.
 */
export enum AGCCloudDBEventType {
    USER_KEY_CHANGED = 1
}
