var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { JsonClientResponse } from "../client/JsonClientResponse";
import { storage as clientStorage } from "../storage";
import { Base64 } from "../util/Base64";
import { FetchClient } from "../ws/FetchClient";
import { DialogRedirectionVisitor } from "./DialogRedirectionVisitor";
import { DialogVisitor } from "./DialogVisitor";
import { LargePropertyVisitor } from "./LargePropertyVisitor";
import { ReadLargePropertyParametersVisitor } from "./ReadLargePropertyParametersVisitor";
import { RecordSetVisitor } from "./RecordSetVisitor";
import { RecordVisitor } from "./RecordVisitor";
// @FIX_THIS
// remove this:
const storage = clientStorage;
// uncomment this
// const storage = clientStorage.getSecureInstance();
// Set the secret key like this:
// storage.secretKey = 'secret_key';
/**
 *
 */
export class DialogProxyTools {
    static captureDialog(userId, baseUrl, tenantId, sessionId, dialogId, referringDialogId) {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::captureDialog';
            // GET DIALOG //
            const resourcePath = `tenants/${tenantId}/sessions/${sessionId}/dialogs/${dialogId}`;
            // Log.info(`${thisMethod} -- capturing online dialog: ${resourcePath}`);
            const dialogJcr = yield DialogProxyTools.commonFetchClient().getJson(baseUrl, resourcePath);
            if (dialogJcr.statusCode !== 200) {
                throw new Error(`Unexpected result when getting dialog ${dialogId}: ${dialogJcr.statusCode}`);
            }
            // Log.info(`${thisMethod} -- dialog: ${JSON.stringify(dialogJcr.value)}`);
            // WRITE DIALOG //
            const dialogVisitor = new DialogVisitor(dialogJcr.value);
            const beforeDialog = dialogVisitor.copyAsJsonObject();
            dialogVisitor.deriveDialogIdsFromDialogNameAndRecordId();
            // Not all referring objects are dialogs, so we must check that a dialog id is present
            if (referringDialogId) {
                dialogVisitor.visitAndSetReferringDialogId(referringDialogId);
            }
            // Log.info(`${thisMethod} -- writing online dialog to offline dialog id: ${dialogVisitor.visitId()}`);
            // Log.info(`${thisMethod} -- writing online dialog to offline storage: ${dialogVisitor.copyAsJsonString()}`);
            yield this.writeDialog(userId, tenantId, dialogVisitor);
            return { beforeDialog, afterDialog: dialogVisitor.enclosedJsonObject() };
        });
    }
    static captureMenuActionRedirectionAndDialog(userId, baseUrl, tenantId, sessionId, dialogId, offlineDialogId, actionId, targetId) {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::captureMenuActionRedirectionAndDialog';
            const resourcePath = `tenants/${tenantId}/sessions/${sessionId}/dialogs/${dialogId}/actions/${actionId}`;
            // Log.info(`${thisMethod} -- capturing menu redirection and dialog: ${resourcePath}`);
            // GET REDIRECTION //
            const actionParameters = {
                targets: [targetId],
                type: "hxgn.api.dialog.ActionParameters"
            };
            // Log.info(`${thisMethod} -- capturing online dialog redirection: ${resourcePath}`);
            const dialogRedirectionJcr = yield DialogProxyTools.commonFetchClient().postJson(baseUrl, resourcePath, actionParameters);
            if (dialogRedirectionJcr.statusCode !== 303) {
                throw new Error(`Unexpected result when posting menu dialog ${dialogId} action ${actionId}: ${dialogRedirectionJcr.statusCode}`);
            }
            // Log.info(`${thisMethod} -- menu action redirection: ${JSON.stringify(dialogRedirectionJcr.value)}`);
            // WRITE REDIRECTION //
            const dialogRedirectionVisitor = new DialogRedirectionVisitor(dialogRedirectionJcr.value);
            const beforeDialogRedirection = dialogRedirectionVisitor.copyAsJsonObject();
            dialogRedirectionVisitor.deriveDialogIdsFromDialogNameAndRecordId();
            dialogRedirectionVisitor.visitAndSetReferringDialogId(offlineDialogId);
            let actionIdAtTargetId = actionId;
            if (targetId) {
                const targetIdEncoded = Base64.encodeUrlSafeString(targetId);
                actionIdAtTargetId = actionIdAtTargetId + '@' + targetIdEncoded;
            }
            // Log.info(`${thisMethod} -- writing online dialog redirection with dialog id: ${dialogRedirectionVisitor.visitDialogId()}`);
            // Log.info(`${thisMethod} -- writing online dialog redirection with referring dialog id: ${dialogRedirectionVisitor.visitReferringDialogId()}`);
            // Log.info(`${thisMethod} -- writing online dialog redirection with record id: ${dialogRedirectionVisitor.visitRecordId()}`);
            // Log.info(`${thisMethod} -- writing online dialog redirection to offline redirection id: ${dialogRedirectionVisitor.visitId()}`);
            // Log.info(`${thisMethod} -- writing online dialog redirection to offline storage: ${dialogRedirectionVisitor.copyAsJsonString()}`);
            const referringDialogId = dialogRedirectionVisitor.visitReferringDialogId();
            yield this.writeDialogRedirection(userId, tenantId, referringDialogId, actionIdAtTargetId, dialogRedirectionVisitor);
            // CAPTURE DIALOG //
            const beforeDialogId = beforeDialogRedirection['dialogId'];
            const beforeAndAfterDialog = yield this.captureDialog(userId, baseUrl, tenantId, sessionId, beforeDialogId, referringDialogId);
            return { beforeDialogRedirection, afterDialogRedirection: dialogRedirectionVisitor.enclosedJsonObject(),
                beforeDialog: beforeAndAfterDialog['beforeDialog'], afterDialog: beforeAndAfterDialog['afterDialog'] };
        });
    }
    static captureRecord(userId, baseUrl, tenantId, sessionId, beforeAndAfterValues, listDialogName) {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::captureRecord';
            // ONLINE
            const onlineRootDialogVisitor = new DialogVisitor(beforeAndAfterValues.beforeDialog);
            const onlineEditorDialogVisitor = onlineRootDialogVisitor.visitChildAtName(listDialogName);
            const onlineEditorDialogId = onlineEditorDialogVisitor.visitId();
            const onlineEditorRecordPath = `tenants/${tenantId}/sessions/${sessionId}/dialogs/${onlineEditorDialogId}/record`;
            // Log.info(`${thisMethod} -- capturing online record: ${onlineEditorRecordPath}`);
            const onlineEditorRecordJcr = yield DialogProxyTools.commonFetchClient().getJson(baseUrl, onlineEditorRecordPath);
            if (onlineEditorRecordJcr.statusCode !== 200) {
                throw new Error(`Unexpected result when getting record: ${onlineEditorRecordJcr.statusCode}`);
            }
            const onlineEditorRecordVisitor = new RecordVisitor(onlineEditorRecordJcr.value);
            // OFFLINE
            const offlineRootDialogVisitor = new DialogVisitor(beforeAndAfterValues.afterDialog);
            const offlineEditorDialogVisitor = offlineRootDialogVisitor.visitChildAtName(listDialogName);
            const offlineEditorDialogId = offlineEditorDialogVisitor.visitId();
            // WRITE TO STORAGE
            // Log.info(`${thisMethod} -- writing online record to offline editor dialog id: ${offlineEditorDialogId}`);
            // Log.info(`${thisMethod} -- writing online record to offline storage: ${onlineEditorRecordVisitor.copyAsJsonString()}`);
            yield DialogProxyTools.writeRecord(userId, tenantId, offlineEditorDialogId, onlineEditorRecordVisitor);
            return onlineEditorRecordVisitor;
        });
    }
    static captureRecordSet(userId, baseUrl, tenantId, sessionId, beforeAndAfterValues, listDialogName) {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::captureRecordSet';
            // ONLINE
            const onlineRootDialogVisitor = new DialogVisitor(beforeAndAfterValues.beforeDialog);
            const onlineQueryDialogVisitor = onlineRootDialogVisitor.visitChildAtName(listDialogName);
            const onlineQueryDialogId = onlineQueryDialogVisitor.visitId();
            const onlineQueryRecordsPath = `tenants/${tenantId}/sessions/${sessionId}/dialogs/${onlineQueryDialogId}/records`;
            const onlineQueryParameters = {
                fetchDirection: "FORWARD",
                fetchMaxRecords: 999,
                type: "hxgn.api.dialog.QueryParameters"
            };
            // Log.info(`${thisMethod} -- capturing online record set: ${onlineQueryRecordsPath}`);
            const onlineQueryRecordsJcr = yield DialogProxyTools.commonFetchClient().postJson(baseUrl, onlineQueryRecordsPath, onlineQueryParameters);
            if (onlineQueryRecordsJcr.statusCode !== 200) {
                throw new Error(`Unexpected result when getting records: ${onlineQueryRecordsJcr.statusCode}`);
            }
            const onlineQueryRecordSetVisitor = new RecordSetVisitor(onlineQueryRecordsJcr.value);
            // OFFLINE
            const offlineRootDialogVisitor = new DialogVisitor(beforeAndAfterValues.afterDialog);
            const offlineQueryDialogVisitor = offlineRootDialogVisitor.visitChildAtName(listDialogName);
            const offlineQueryDialogId = offlineQueryDialogVisitor.visitId();
            // WRITE TO STORAGE
            // Log.info(`${thisMethod} -- writing online record set to offline query dialog id: ${offlineQueryDialogId}`);
            // Log.info(`${thisMethod} -- writing online record set to offline storage: ${onlineQueryRecordSetVisitor.copyAsJsonString()}`);
            yield DialogProxyTools.writeRecordSet(userId, tenantId, offlineQueryDialogId, onlineQueryRecordSetVisitor);
            return onlineQueryRecordSetVisitor;
        });
    }
    static captureWorkbenchActionRedirectionAndDialog(userId, baseUrl, tenantId, sessionId, workbenchId, actionId) {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::captureWorkbenchActionRedirectionAndDialog';
            const resourcePath = `tenants/${tenantId}/sessions/${sessionId}/workbenches/${workbenchId}/actions/${actionId}`;
            // Log.info(`${thisMethod} -- capturing workbench redirection and dialog: ${resourcePath}`);
            // GET REDIRECTION //
            // Log.info(`${thisMethod} -- capturing online dialog redirection: ${resourcePath}`);
            const dialogRedirectionJcr = yield DialogProxyTools.commonFetchClient().postJson(baseUrl, resourcePath, {});
            if (dialogRedirectionJcr.statusCode !== 303) {
                throw new Error(`Unexpected result when posting workbench ${workbenchId} action ${actionId}: ${dialogRedirectionJcr.statusCode}`);
            }
            // Log.info(`${thisMethod} -- workbench action redirection: ${JSON.stringify(dialogRedirectionJcr.value)}`);
            // WRITE REDIRECTION //
            const dialogRedirectionVisitor = new DialogRedirectionVisitor(dialogRedirectionJcr.value);
            const beforeDialogRedirection = dialogRedirectionVisitor.copyAsJsonObject();
            dialogRedirectionVisitor.deriveDialogIdsFromDialogNameAndRecordId();
            // Log.info(`${thisMethod} -- writing online dialog redirection to offline redirection id: ${dialogRedirectionVisitor.visitId()}`);
            // Log.info(`${thisMethod} -- writing online dialog redirection to offline storage: ${dialogRedirectionVisitor.copyAsJsonString()}`);
            yield this.writeDialogRedirection(userId, tenantId, workbenchId, actionId, dialogRedirectionVisitor);
            // CAPTURE DIALOG //
            const beforeDialogId = beforeDialogRedirection['dialogId'];
            const beforeAndAfterDialog = yield this.captureDialog(userId, baseUrl, tenantId, sessionId, beforeDialogId, null);
            return { beforeDialogRedirection, afterDialogRedirection: dialogRedirectionVisitor.enclosedJsonObject(),
                beforeDialog: beforeAndAfterDialog['beforeDialog'], afterDialog: beforeAndAfterDialog['afterDialog'] };
        });
    }
    static clearAllStorageAt(userId, tenantId) {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::clearAllStorageAt';
            let prefix = this.STORAGE_KEY_PREFIX.replace('${userId}', userId);
            prefix = prefix.replace('${tenantId}', tenantId);
            // Log.info(`${thisMethod} -- ************** BEGIN CLEAR ALL STORAGE AT **************`);
            const allKeys = yield storage.getAllKeys();
            for (const k of allKeys) {
                if (k.startsWith(prefix)) {
                    yield storage.removeItem(k);
                    // Log.info(`${thisMethod} -- Removed from storage: ${k}`);
                }
            }
            // Log.info(`${thisMethod} -- ************** END CLEAR ALL STORAGE AT **************`);
        });
    }
    static commonFetchClient() {
        return this.COMMON_FETCH_CLIENT;
    }
    static constructDialogMessageModel(message) {
        return { type: this.DIALOG_MESSAGE_MODEL_TYPE, message };
    }
    static constructLoginModel(userId, password) {
        return {
            "userId": userId,
            "password": password,
            "clientType": "MOBILE",
            "deviceProperties": {},
            "type": this.LOGIN_MODEL_TYPE
        };
    }
    static constructRedirectionStorageKey(userId, tenantId, stateId, actionId) {
        let key = this.REDIRECTION_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${stateId}', stateId);
        key = key.replace('${actionId}', actionId);
        return key;
    }
    static constructRequestNotValidDuringOfflineMode(action, resourcePath) {
        return new JsonClientResponse(this.constructDialogMessageModel(`${action} at ${resourcePath} is not valid during offline mode: `), 400);
    }
    /**
     * Construct an empty null redirection with the following defaults:
     * referringObject will be a type of "hxgn.api.dialog.ReferringDialog"
     *      dialogAlias=null
     *      dialogName=null
     *      dialogMode='READ'
     *      actionId=null
     *      dialogId=null
     * refreshNeeded=true
     * id=randomly generated value
     */
    static constructNullRedirection(tenantId, sessionId) {
        const nullRedirectionId = DialogProxyTools.constructNullRedirectionId();
        return {
            "tenantId": tenantId,
            "referringObject": {
                "dialogMode": "READ",
                "dialogAlias": null,
                "dialogName": null,
                "actionId": null,
                "type": "hxgn.api.dialog.ReferringDialog",
                "dialogId": null
            },
            "refreshNeeded": true,
            "sessionId": sessionId,
            "id": nullRedirectionId,
            "type": "hxgn.api.dialog.NullRedirection"
        };
    }
    static constructNullRedirectionId() {
        return `null_redirection__offline_${Date.now()}`;
    }
    // ----- MODEL QUERY METHODS ----- //
    static isActionParametersModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.ACTION_PARAMETERS_MODEL_TYPE;
    }
    static isAnnotationModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.ANNOTATION_MODEL_TYPE;
    }
    static isDialogModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.EDITOR_DIALOG_MODEL_TYPE ||
            jsonObject['type'] === this.QUERY_DIALOG_MODEL_TYPE;
    }
    static isLoginModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.LOGIN_MODEL_TYPE;
    }
    static isPropertyModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.PROPERTY_MODEL_TYPE;
    }
    static isPropertyDefModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.PROPERTY_DEF_MODEL_TYPE;
    }
    static isRecordModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.RECORD_MODEL_TYPE;
    }
    static isRecordSetModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.RECORD_SET_MODEL_TYPE;
    }
    static isReferringDialogModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.REFERRING_DIALOG_MODEL_TYPE;
    }
    static isReferringWorkbenchModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.REFERRING_WORKBENCH_MODEL_TYPE;
    }
    static isSessionModel(jsonObject) {
        if (!jsonObject || !jsonObject['type']) {
            return false;
        }
        return jsonObject['type'] === this.SESSION_MODEL_TYPE;
    }
    // ----- PATH QUERY METHODS ----- //
    static readDialogAsOfflineResponse(userId, request) {
        return this.readDialogAsVisitor(userId, request).then(dialogVisitor => {
            return dialogVisitor ?
                new JsonClientResponse(dialogVisitor.enclosedJsonObject(), 200) :
                this.constructRequestNotValidDuringOfflineMode('readDialogAsOfflineResponse', request.resourcePath());
        });
    }
    static readDialogAsVisitor(userId, request) {
        const thisMethod = 'DialogProxyTools::readDialogAsVisitor';
        const pathFields = request.deconstructGetDialogPath();
        const tenantId = pathFields.tenantId;
        const sessionId = pathFields.sessionId;
        const dialogId = pathFields.dialogId;
        let key = this.DIALOG_STORAGE_KEY.replace('${tenantId}', tenantId);
        key = key.replace('${userId}', userId);
        key = key.replace('${dialogId}', dialogId);
        // Log.info(`${thisMethod} -- reading for dialog at key: ${key}`);
        return storage.getJson(key).then(jsonObject => jsonObject ? new DialogVisitor(jsonObject) : null);
    }
    static readDialogRedirectionAsVisitor(userId, tenantId, stateId, actionId) {
        const thisMethod = 'DialogProxyTools::readDialogRedirectionAsVisitor';
        const key = this.constructRedirectionStorageKey(userId, tenantId, stateId, actionId);
        // Log.info(`${thisMethod} -- reading for redirection at key: ${key}`);
        return storage.getJson(key).then(jsonObject => jsonObject ? new DialogRedirectionVisitor(jsonObject) : null);
    }
    static readMenuActionRedirectionAsOfflineResponse(userId, request) {
        return this.readMenuActionRedirectionAsVisitor(userId, request).then(dialogRedirectionVisitor => {
            return dialogRedirectionVisitor ?
                new JsonClientResponse(dialogRedirectionVisitor.enclosedJsonObject(), 303) :
                this.constructRequestNotValidDuringOfflineMode('readMenuActionRedirectionAsOfflineResponse', request.resourcePath());
        });
    }
    static readMenuActionRedirectionAsVisitor(userId, request) {
        const pathFields = request.deconstructPostMenuActionPath();
        let actionIdAtTargetId = request.actionId();
        const targetId = request.targetId();
        if (targetId) {
            const targetIdEncoded = Base64.encodeUrlSafeString(targetId);
            actionIdAtTargetId = `${request.actionId()}@${targetIdEncoded}`;
        }
        return this.readDialogRedirectionAsVisitor(userId, pathFields.tenantId, pathFields.dialogId, actionIdAtTargetId);
    }
    static readPropertyCommit(userId, tenantId, dialogId, propertyName) {
        let key = this.PROPERTY_COMMIT_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${dialogId}', dialogId);
        key = key.replace('${propertyName}', propertyName);
        return storage.getJson(key);
    }
    static readRecordAsOfflineResponse(userId, request) {
        return this.readRecordAsVisitorFromRequest(userId, request).then(recordVisitor => {
            return recordVisitor ?
                new JsonClientResponse(recordVisitor.enclosedJsonObject(), 200) :
                this.constructRequestNotValidDuringOfflineMode('readRecordAsOfflineResponse', request.resourcePath());
        });
    }
    static readRecordAsVisitor(userId, tenantId, dialogId) {
        let key = this.RECORD_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${dialogId}', dialogId);
        return storage.getJson(key).then(jsonObject => jsonObject ? new RecordVisitor(jsonObject) : null);
    }
    static readRecordAsVisitorFromRequest(userId, request) {
        const pathFields = request.deconstructGetRecordPath();
        const tenantId = pathFields.tenantId;
        const dialogId = pathFields.dialogId;
        return this.readRecordAsVisitor(userId, tenantId, dialogId);
    }
    static readRecordCommitAsVisitor(userId, tenantId, dialogId) {
        let key = this.RECORD_COMMIT_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${dialogId}', dialogId);
        return storage.getJson(key).then(jsonObject => jsonObject ? new RecordVisitor(jsonObject) : null);
    }
    static readRecordSetAsOfflineResponse(userId, request) {
        return this.readRecordSetAsVisitor(userId, request).then(recordSetVisitor => {
            return recordSetVisitor ?
                new JsonClientResponse(recordSetVisitor.enclosedJsonObject(), 200) :
                this.constructRequestNotValidDuringOfflineMode('readRecordSetAsOfflineResponse', request.resourcePath());
        });
    }
    static readRecordSetAsVisitor(userId, request) {
        return __awaiter(this, void 0, void 0, function* () {
            const pathFields = request.deconstructPostRecordsPath();
            const tenantId = pathFields.tenantId;
            const sessionId = pathFields.sessionId;
            const dialogId = pathFields.dialogId;
            let key = this.RECORD_SET_STORAGE_KEY.replace('${tenantId}', tenantId);
            key = key.replace('${userId}', userId);
            key = key.replace('${dialogId}', dialogId);
            const jsonObject = yield storage.getJson(key);
            if (!jsonObject) {
                return null;
            }
            const recordSetVisitor = new RecordSetVisitor(jsonObject);
            if (request.body().fromRecordId) {
                recordSetVisitor.fromRecordId(request.body().fromRecordId);
            }
            return recordSetVisitor;
        });
    }
    static readSessionContentAsOfflineResponse(userId, request) {
        const pathFields = request.deconstructPostSessionContentPath();
        const tenantId = pathFields.tenantId;
        const contentId = pathFields.contentId;
        const parametersVisitor = new ReadLargePropertyParametersVisitor(request.body());
        const sequence = parametersVisitor.visitSequence();
        return this.readSessionContentAsVisitor(userId, tenantId, contentId, sequence).then(largePropertyVisitor => {
            return largePropertyVisitor ?
                new JsonClientResponse(largePropertyVisitor.enclosedJsonObject(), 200) :
                this.constructRequestNotValidDuringOfflineMode('readSessionContentAsOfflineResponse', request.resourcePath());
        });
    }
    static readSessionContentAsVisitor(userId, tenantId, contentId, sequence) {
        let key = this.CONTENT_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${contentId}', contentId);
        key = key.replace('${sequence}', sequence.toString());
        return storage.getJson(key).then(jsonObject => jsonObject ? new LargePropertyVisitor(jsonObject) : null);
    }
    static readWorkbenchActionRedirectionAsOfflineResponse(userId, request) {
        const pathFields = request.deconstructPostWorkbenchActionPath();
        return this.readDialogRedirectionAsVisitor(userId, pathFields.tenantId, pathFields.workbenchId, pathFields.actionId).then(dialogRedirectionVisitor => {
            return dialogRedirectionVisitor ?
                new JsonClientResponse(dialogRedirectionVisitor.enclosedJsonObject(), 303) :
                this.constructRequestNotValidDuringOfflineMode('readWorkbenchActionRedirectionAsOfflineResponse', request.resourcePath());
        });
    }
    static showStoredDialogNavigation() {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::showAllRedirectionStorageKeys';
            // Log.info(`${thisMethod} -- ************** BEGIN SHOW ALL REDIRECTION STORAGE KEYS **************`);
            const allKeys = yield storage.getAllKeys();
            for (const k of allKeys) {
                if (k.endsWith('.redirection')) {
                    const redirection = yield storage.getJson(k);
                    // Log.info(`${thisMethod} -- ${k} => \n${redirection.dialogName}(id=${redirection.id})\n`);
                }
            }
            // Log.info(`${thisMethod} -- ************** END SHOW ALL REDIRECTION STORAGE KEYS **************`);
        });
    }
    static showAllStorageKeys() {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::showAllStorageKeys';
            // Log.info(`${thisMethod} -- ************** BEGIN SHOW ALL STORAGE KEYS **************`);
            const allKeys = yield storage.getAllKeys();
            for (const k of allKeys) {
                const v = yield clientStorage.getItem(k);
                // Log.info(`${thisMethod} -- ${k}`);
            }
            // Log.info(`${thisMethod} -- ************** END SHOW ALL STORAGE KEYS **************`);
        });
    }
    static showAllStorageKeysAndValues() {
        return __awaiter(this, void 0, void 0, function* () {
            const thisMethod = 'DialogProxyTools::showAllStorageKeysAndValues';
            // Log.info(`${thisMethod} -- ************** BEGIN SHOW ALL STORAGE KEYS AND VALUES **************`);
            const allKeys = yield storage.getAllKeys();
            for (const k of allKeys) {
                const v = yield clientStorage.getItem(k);
                // Log.info(`${thisMethod} -- ${k}: ${v}`);
            }
            // Log.info(`${thisMethod} -- ************** END SHOW ALL STORAGE KEYS AND VALUES **************`);
        });
    }
    static writeContentChunk(userId, tenantId, contentId, sequence, largePropertyVisitor) {
        let key = this.CONTENT_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${contentId}', contentId);
        key = key.replace('${sequence}', sequence.toString());
        return storage.setJson(key, largePropertyVisitor.enclosedJsonObject());
    }
    static writeContentRedirection(userId, tenantId, stateId, actionId, contentRedirectionVistor) {
        const key = this.constructRedirectionStorageKey(userId, tenantId, stateId, actionId);
        return storage.setJson(key, contentRedirectionVistor.enclosedJsonObject());
    }
    static writeDialog(userId, tenantId, dialogVisitor) {
        let key = this.DIALOG_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${dialogId}', dialogVisitor.visitId());
        return storage.setJson(key, dialogVisitor.enclosedJsonObject());
    }
    static writeDialogRedirection(userId, tenantId, stateId, actionId, dialogRedirectionVistor) {
        const key = this.constructRedirectionStorageKey(userId, tenantId, stateId, actionId);
        return storage.setJson(key, dialogRedirectionVistor.enclosedJsonObject());
    }
    static writePropertyCommit(userId, tenantId, dialogId, propertyName, writeLargePropertyParametersVisitor) {
        return __awaiter(this, void 0, void 0, function* () {
            let key = this.PROPERTY_COMMIT_STORAGE_KEY.replace('${userId}', userId);
            key = key.replace('${tenantId}', tenantId);
            key = key.replace('${dialogId}', dialogId);
            key = key.replace('${propertyName}', propertyName);
            let writeHistory = [];
            if (writeLargePropertyParametersVisitor.visitAppend()) {
                const jsonObject = yield storage.getJson(key);
                if (jsonObject) {
                    writeHistory = jsonObject;
                }
            }
            writeHistory.push(writeLargePropertyParametersVisitor.enclosedJsonObject());
            return storage.setJson(key, writeHistory);
        });
    }
    static writeRecord(userId, tenantId, dialogId, recordVisitor) {
        let key = this.RECORD_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${dialogId}', dialogId);
        return storage.setJson(key, recordVisitor.enclosedJsonObject());
    }
    static writeRecordCommit(userId, tenantId, dialogId, recordVisitor) {
        let key = this.RECORD_COMMIT_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${dialogId}', dialogId);
        return storage.setJson(key, recordVisitor.enclosedJsonObject());
    }
    static writeRecordSet(userId, tenantId, dialogId, recordSetVisitor) {
        let key = this.RECORD_SET_STORAGE_KEY.replace('${userId}', userId);
        key = key.replace('${tenantId}', tenantId);
        key = key.replace('${dialogId}', dialogId);
        return storage.setJson(key, recordSetVisitor.enclosedJsonObject());
    }
}
// Model Types
DialogProxyTools.ACTION_PARAMETERS_MODEL_TYPE = 'hxgn.api.dialog.ActionParameters';
DialogProxyTools.ANNOTATION_MODEL_TYPE = 'hxgn.api.dialog.Annotation';
DialogProxyTools.DIALOG_MESSAGE_MODEL_TYPE = 'hxgn.api.dialog.DialogMessage';
DialogProxyTools.EDITOR_DIALOG_MODEL_TYPE = 'hxgn.api.dialog.EditorDialog';
DialogProxyTools.LOGIN_MODEL_TYPE = 'hxgn.api.dialog.Login';
DialogProxyTools.PROPERTY_MODEL_TYPE = 'hxgn.api.dialog.Property';
DialogProxyTools.PROPERTY_DEF_MODEL_TYPE = 'hxgn.api.dialog.PropertyDef';
DialogProxyTools.QUERY_DIALOG_MODEL_TYPE = 'hxgn.api.dialog.QueryDialog';
DialogProxyTools.RECORD_MODEL_TYPE = 'hxgn.api.dialog.Record';
DialogProxyTools.RECORD_SET_MODEL_TYPE = 'hxgn.api.dialog.RecordSet';
DialogProxyTools.REFERRING_DIALOG_MODEL_TYPE = 'hxgn.api.dialog.ReferringDialog';
DialogProxyTools.REFERRING_WORKBENCH_MODEL_TYPE = 'hxgn.api.dialog.ReferringWorkbench';
DialogProxyTools.SESSION_MODEL_TYPE = 'hxgn.api.dialog.Session';
// Storage Keys
DialogProxyTools.CONTENT_STORAGE_KEY = '${userId}.${tenantId}.${contentId}.${sequence}.content';
DialogProxyTools.DIALOG_STORAGE_KEY = '${userId}.${tenantId}.${dialogId}.dialog';
DialogProxyTools.PROPERTY_COMMIT_STORAGE_KEY = '${userId}.${tenantId}.${dialogId}.${propertyName}.propertycommit';
DialogProxyTools.RECORD_COMMIT_STORAGE_KEY = '${userId}.${tenantId}.${dialogId}.recordcommit';
DialogProxyTools.RECORD_SET_STORAGE_KEY = '${userId}.${tenantId}.${dialogId}.recordset';
DialogProxyTools.RECORD_STORAGE_KEY = '${userId}.${tenantId}.${dialogId}.record';
DialogProxyTools.REDIRECTION_STORAGE_KEY = '${userId}.${tenantId}.${stateId}.${actionId}.redirection';
DialogProxyTools.STORAGE_KEY_PREFIX = '${userId}.${tenantId}.';
DialogProxyTools.COMMON_FETCH_CLIENT = new FetchClient();
