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

import AGCCloudDBZone from "./AGCCloudDBZone";
import { CloudDBZoneConfig } from "./interfaces";
import { asyncExec, randomNumber } from "./utils";
import AGCCloudDBQuery from './AGCCloudDBQuery';
import AGCCloudDBTransaction from './AGCCloudDBTransaction';
import { AGCCloudDBEventType } from "./enums";

export * from './interfaces';
export * from './enums';
export { AGCCloudDBQuery, AGCCloudDBTransaction }

/**
 * Initializes AGConnectCloudDB.
 */
export function initialize(): Promise<void> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["initialize"]);
}

/**
 * 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.
 */
export function createObjectType(): Promise<void> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["createObjectType"]);
}

/**
 * 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.
 */
export function getCloudDBZoneConfigs(): Promise<CloudDBZoneConfig[]> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["getCloudDBZoneConfigs"]);
}

/**
 * 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.
 */
export async function openCloudDBZone2(config: CloudDBZoneConfig, isAllowToCreate: boolean): Promise<AGCCloudDBZone> {
    let id = randomNumber().toString();
    await asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["openCloudDBZone2", config, isAllowToCreate, id]);
    return new AGCCloudDBZone(id);
}

/**
 * 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.
 */
export async function openCloudDBZone(config: CloudDBZoneConfig, isAllowToCreate: boolean): Promise<AGCCloudDBZone> {
    let id = randomNumber().toString();
    await asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["openCloudDBZone", config, isAllowToCreate, id]);
    return new AGCCloudDBZone(id);
}

/**
 * Listens to registered user key change events.
 * @param callback Callback function to be called when listener is triggered.
 */
export function addEventListener(callback: (eventType: AGCCloudDBEventType) => void): Promise<void> {
    window.subscribeAGCEvent("onUserKeyChange", callback);
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["addEventListener"]);
}

/**
 * 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.
 */
export function addDataEncryptionKeyListener(needFetchDataEncryptionKey: boolean, callback: (isDataKeyChange: boolean) => void): Promise<void> {
    window.subscribeAGCEvent("onDataKeyChange", callback);
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["addDataEncryptionKeyListener", needFetchDataEncryptionKey]);
}

/**
 * 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.
 */
export function deleteCloudDBZone(zoneName: string): Promise<void> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["deleteCloudDBZone", zoneName]);
}

/**
 * Closes the Cloud DB zone object opened on the device.
 * @param id An id of Cloud DB zone to be closed.
 */
export function closeCloudDBZone(id: string): Promise<void> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["closeCloudDBZone", id]);
}

/**
 * Enables data synchronization between the device and cloud.
 * @param zoneName Cloud DB zone name
 */
export function enableNetwork(zoneName: string): Promise<void> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["enableNetwork", zoneName]);
}

/**
 * Disables data synchronization between the device and cloud.
 * @param zoneName Cloud DB zone name
 */
export function disableNetwork(zoneName: string): Promise<void> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["disableNetwork", zoneName]);
}

/**
 * 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.
 */
export function updateDataEncryptionKey(): Promise<boolean> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["updateDataEncryptionKey"]);
}

/**
 * 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.
 */
export function setUserKey(userKey: string, userReKey: string): Promise<boolean> {
    return asyncExec('AGCCloudDBPlugin', "AGCCloudDBService", ["setUserKey", userKey, userReKey]);
}
