"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.Cache = exports.threadAddr = exports.createThread = exports.decodeRecord = void 0;
const threads_core_1 = require("@textile/threads-core");
const threads_encoding_1 = require("@textile/threads-encoding");
const libp2p_crypto_1 = require("libp2p-crypto");
const ed25519 = libp2p_crypto_1.keys.supportedKeys.ed25519;
function decodeRecord(rec, info) {
    if (!info.key || !rec.record)
        return; // Don't have the right keys!
    const event = rec.record.block;
    if (info.key.read === undefined)
        return;
    const decodedHeader = threads_encoding_1.decodeBlock(event.header, info.key.read);
    const header = decodedHeader.decodeUnsafe();
    if (!header.key)
        return;
    const decodedBody = threads_encoding_1.decodeBlock(event.body, header.key);
    return decodedBody.decode();
}
exports.decodeRecord = decodeRecord;
function createThread(network, id = threads_core_1.ThreadID.fromRandom(threads_core_1.ThreadID.Variant.Raw, 32)) {
    return __awaiter(this, void 0, void 0, function* () {
        const threadKey = threads_core_1.ThreadKey.fromRandom(true);
        // @todo: Let users/developers provide their own keys here.
        const logKey = yield ed25519.generateKeyPair();
        return network.createThread(id, { threadKey, logKey });
    });
}
exports.createThread = createThread;
function threadAddr(hostAddr, hostID, threadID) {
    const pa = new threads_core_1.Multiaddr(`/p2p/${hostID}`);
    const ta = new threads_core_1.Multiaddr(`/thread/${threadID}`);
    return hostAddr.encapsulate(pa.encapsulate(ta));
}
exports.threadAddr = threadAddr;
function Cache(params = {}) {
    const defaultValues = {
        duration: 3000,
    };
    params = Object.assign(Object.assign({}, defaultValues), params);
    let originalFunc;
    let value;
    let cacheUntil;
    let funcType;
    const cacheValue = (val, now) => {
        cacheUntil = params.duration ? new Date(now.getTime() + params.duration) : undefined;
        value = val;
    };
    return function (_target, _propertyKey, descriptor) {
        originalFunc = descriptor.value;
        descriptor.value = function () {
            const now = new Date();
            if (value && cacheUntil && cacheUntil > now) {
                switch (funcType) {
                    case 'promise':
                        return Promise.resolve(value);
                    default:
                        return value;
                }
            }
            const result = originalFunc.apply(this);
            if (result instanceof Promise) {
                funcType = 'promise';
                return result.then(value => {
                    cacheValue(value, now);
                    return value;
                });
            }
            else {
                funcType = 'value';
                cacheValue(result, now);
                return result;
            }
        };
    };
}
exports.Cache = Cache;
//# sourceMappingURL=utils.js.map