"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DidResolver = void 0;
const did_js_1 = require("./did.js");
const did_ion_resolver_js_1 = require("./did-ion-resolver.js");
const did_key_resolver_js_1 = require("./did-key-resolver.js");
const memory_cache_js_1 = require("../utils/memory-cache.js");
/**
 * A DID resolver that by default supports `did:key` and `did:ion` DIDs.
 */
class DidResolver {
    constructor(resolvers, cache) {
        this.cache = cache || new memory_cache_js_1.MemoryCache(600);
        // construct default DID method resolvers if none given
        if (resolvers === undefined || resolvers.length === 0) {
            resolvers = [
                new did_ion_resolver_js_1.DidIonResolver(),
                new did_key_resolver_js_1.DidKeyResolver()
            ];
        }
        this.didResolvers = new Map();
        for (const resolver of resolvers) {
            this.didResolvers.set(resolver.method(), resolver);
        }
    }
    /**
     * attempt to resolve the DID provided
     * @throws {Error} if DID is invalid
     * @throws {Error} if DID method is not supported
     * @throws {Error} if resolving DID fails
     * @param did - the DID to resolve
     * @returns {DidResolutionResult}
     */
    resolve(did) {
        return __awaiter(this, void 0, void 0, function* () {
            // naively validate author DID
            did_js_1.Did.validate(did);
            const splitDID = did.split(':', 3);
            const didMethod = splitDID[1];
            const didResolver = this.didResolvers.get(didMethod);
            if (!didResolver) {
                throw new Error(`${didMethod} DID method not supported`);
            }
            // use cached result if exists
            const cachedResolutionResult = yield this.cache.get(did);
            const resolutionResult = cachedResolutionResult !== null && cachedResolutionResult !== void 0 ? cachedResolutionResult : yield didResolver.resolve(did);
            if (cachedResolutionResult === undefined) {
                yield this.cache.set(did, resolutionResult);
            }
            const { didDocument, didResolutionMetadata } = resolutionResult;
            if (!didDocument || (didResolutionMetadata === null || didResolutionMetadata === void 0 ? void 0 : didResolutionMetadata.error)) {
                const { error } = didResolutionMetadata;
                let errMsg = `Failed to resolve DID ${did}.`;
                errMsg += error ? ` Error: ${error}` : '';
                throw new Error(errMsg);
            }
            return resolutionResult;
        });
    }
    dump() {
        var _a, _b, _c;
        return __awaiter(this, void 0, void 0, function* () {
            console.group('didResolvers');
            for (const [key, value] of this.didResolvers) {
                console.group(key);
                // @ts-ignore
                yield ((_a = value['dump']) === null || _a === void 0 ? void 0 : _a.call(value));
                console.groupEnd();
            }
            console.groupEnd();
            console.group('didCache');
            // @ts-ignore
            yield ((_c = (_b = this.cache)['dump']) === null || _c === void 0 ? void 0 : _c.call(_b));
            console.groupEnd();
        });
    }
}
exports.DidResolver = DidResolver;
//# sourceMappingURL=did-resolver.js.map