"use strict";
/* eslint-disable indent */
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ITwinRealityData = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const RequestOptions_1 = require("./RequestOptions");
const axios_1 = __importDefault(require("axios"));
/**
 * Cache parameters for reality data access. Contains the blob url, the timestamp to refresh (every 50 minutes) the url and the root document path.
 * Cache contains one value for the read permission url, and one of the write permission.
 * */
class ContainerCache {
    getCache(access) {
        if (access === "Read")
            return this._containerRead;
        else
            return this._containerWrite;
    }
    setCache(containerCacheValue, access) {
        if (access === "Read")
            this._containerRead = containerCacheValue;
        else
            this._containerWrite = containerCacheValue;
    }
}
/** RealityData
 * This class implements a Reality Data instance.
 * Data is accessed directly through methods of the reality data instance.
 * Access to the data required a properly entitled token though the access to the blob is controlled through
 * an Azure blob URL, the token may be required to obtain this Azure blob URL or refresh it.
 * The Azure blob URL is considered valid for an hour and is refreshed after 50 minutes.
 * In addition to the reality data properties, and Azure blob URL and internal states, a reality data also contains
 * the identification of the iTwin to be used for access permissions and
 * may contain a RealityDataClient to obtain the specialization to communicate with Reality Management API (to obtain the Azure blob URL).
 * @beta
 */
class ITwinRealityData {
    /**
     * Creates an instance of RealityData.
     * @beta
     */
    constructor(client, realityData, iTwinId) {
        this.client = client;
        this._containerCache = new ContainerCache();
        if (realityData) {
            this.id = realityData.id;
            this.displayName = realityData.displayName;
            this.dataset = realityData.dataset;
            this.group = realityData.group;
            this.dataCenterLocation = realityData.dataCenterLocation;
            this.description = realityData.description;
            this.rootDocument = realityData.rootDocument;
            this.tags = realityData.tags;
            if (realityData.acquisition) {
                this.acquisition = realityData.acquisition;
                this.acquisition.startDateTime = new Date(realityData.acquisition.startDateTime);
                this.acquisition.endDateTime = realityData.acquisition.endDateTime ? new Date(realityData.acquisition.endDateTime) : undefined;
                this.acquisition.acquirer = realityData.acquisition.acquirer ? realityData.acquisition.acquirer : undefined;
            }
            this.size = realityData.size;
            this.authoring = realityData.authoring;
            this.classification = realityData.classification;
            this.type = realityData.type;
            this.extent = realityData.extent;
            // eslint-disable-next-line deprecation/deprecation
            this.accessControl = realityData.accessControl;
            this.modifiedDateTime = new Date(realityData.modifiedDateTime);
            this.lastAccessedDateTime = new Date(realityData.lastAccessedDateTime);
            this.createdDateTime = new Date(realityData.createdDateTime);
        }
        if (iTwinId)
            this.iTwinId = iTwinId;
    }
    /**
       * Gets string url to fetch blob data from. Access is read-only.
       * @param accessToken The client request context.
       * @param blobPath name or path of tile
       * @param writeAccess Optional boolean indicating if write access is requested. Default is false for read-only access. The realitydata:modify scope is required to grant the "write" access.
       * @returns string url for blob data
       * @beta
       */
    async getBlobUrl(accessToken, blobPath, writeAccess = false) {
        const accessTokenResolved = await this.resolveAccessToken(accessToken);
        const url = await this.getContainerUrl(accessTokenResolved, writeAccess);
        if (blobPath === undefined)
            return url;
        const host = `${url.origin + url.pathname}/`;
        const query = url.search;
        return new URL(`${host}${blobPath}${query}`);
    }
    /**
     * Try to use authorizationClient in RealityDataClientOptions to get the access token
     * otherwise, will return the input token
     * This is a workaround to support different authorization client for the reality data client and iTwin-core.
     */
    async resolveAccessToken(accessToken) {
        return this.client?.authorizationClient ? this.client.authorizationClient.getAccessToken() : accessToken;
    }
    /**
       * Gets a tile access url URL object
       * @param accessToken The client request context.
       * @param writeAccess Optional boolean indicating if write access is requested. Default is false for read-only access.
       * @returns app URL object for blob url
       * @beta
       */
    async getContainerUrl(accessToken, writeAccess = false) {
        if (!this.client)
            throw new core_bentley_1.BentleyError(422, "Invalid container request (RealityDataAccessClient is not set).");
        const access = (writeAccess === true ? "Write" : "Read");
        const accessTokenResolved = await this.resolveAccessToken(accessToken);
        try {
            const containerCache = this._containerCache.getCache(access);
            const blobUrlRequiresRefresh = !containerCache?.timeStamp || (Date.now() - containerCache?.timeStamp.getTime()) > 3000000; // 3 million milliseconds or 50 minutes
            if (undefined === containerCache?.url || blobUrlRequiresRefresh) {
                const url = new URL(`${this.client.baseUrl}/${this.id}/${writeAccess === true ? "writeAccess" : "readAccess"}`);
                if (this.iTwinId)
                    url.searchParams.append("iTwinId", this.iTwinId);
                const requestOptions = (0, RequestOptions_1.getRequestConfig)(accessTokenResolved, "GET", url.href, this.client.apiVersion);
                const response = await axios_1.default.get(url.href, requestOptions);
                if (!response.data) {
                    throw new core_bentley_1.BentleyError(422, "Invalid container request (API returned an unexpected response).");
                }
                // update cache
                const newContainerCacheValue = {
                    url: new URL(response.data._links.containerUrl.href),
                    timeStamp: new Date(Date.now()),
                };
                this._containerCache.setCache(newContainerCacheValue, access);
            }
            return this._containerCache.getCache(access).url;
        }
        catch (errorResponse) {
            throw new core_bentley_1.BentleyError(422, "Invalid container request.");
        }
    }
}
exports.ITwinRealityData = ITwinRealityData;
//# sourceMappingURL=RealityData.js.map