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());
    });
};
import { DwnInterfaceName, DwnMethodName } from '../../src/index.js';
import * as cbor from '@ipld/dag-cbor';
import { CID } from 'multiformats/cid';
import { DataStream } from '../../src/utils/data-stream.js';
import { getCurrentTimeInHighPrecision } from '../../src/utils/time.js';
import { PermissionsGrant } from '../../src/interfaces/permissions-grant.js';
import { PermissionsRequest } from '../../src/interfaces/permissions-request.js';
import { PermissionsRevoke } from '../../src/interfaces/permissions-revoke.js';
import { removeUndefinedProperties } from '../../src/utils/object.js';
import { Secp256k1 } from '../../src/utils/secp256k1.js';
import { sha256 } from 'multiformats/hashes/sha2';
import { Temporal } from '@js-temporal/polyfill';
import { DidKeyResolver, EventsGet, HooksWrite, Jws, MessagesGet, ProtocolsConfigure, ProtocolsQuery, RecordsDelete, RecordsQuery, RecordsWrite } from '../../src/index.js';
/**
 * Utility class for generating data for testing.
 */
export class TestDataGenerator {
    /**
     * Generates a persona.
     */
    static generatePersona(input) {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            // generate DID if not given
            let did = input === null || input === void 0 ? void 0 : input.did;
            if (!did) {
                const didSuffix = TestDataGenerator.randomString(32);
                did = `did:example:${didSuffix}`;
            }
            // generate persona key ID if not given
            const keyIdSuffix = TestDataGenerator.randomString(10);
            const keyId = (_a = input === null || input === void 0 ? void 0 : input.keyId) !== null && _a !== void 0 ? _a : `${did}#${keyIdSuffix}`;
            // generate persona key pair if not given
            const keyPair = (_b = input === null || input === void 0 ? void 0 : input.keyPair) !== null && _b !== void 0 ? _b : yield Secp256k1.generateKeyPair();
            const persona = {
                did,
                keyId,
                keyPair
            };
            return persona;
        });
    }
    /**
     * Generates a ProtocolsConfigure message for testing.
     * Optional parameters are generated if not given.
     * Implementation currently uses `ProtocolsConfigure.create()`.
     */
    static generateProtocolsConfigure(input) {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield TestDataGenerator.generatePersona();
            // generate protocol types and  definition if not given
            let definition = input === null || input === void 0 ? void 0 : input.protocolDefinition;
            if (!definition) {
                const generatedLabel = 'record' + TestDataGenerator.randomString(10);
                definition = {
                    protocol: TestDataGenerator.randomString(20),
                    published: (_b = input === null || input === void 0 ? void 0 : input.published) !== null && _b !== void 0 ? _b : false,
                    types: {},
                    structure: {}
                };
                definition.types[generatedLabel] = {
                    schema: `test-object`,
                    dataFormats: ['text/plain']
                };
                definition.structure[generatedLabel] = {};
            }
            const dataStream = undefined;
            const authorizationSignatureInput = Jws.createSignatureInput(author);
            const options = {
                messageTimestamp: input === null || input === void 0 ? void 0 : input.messageTimestamp,
                definition,
                authorizationSignatureInput,
                permissionsGrantId: input === null || input === void 0 ? void 0 : input.permissionsGrantId
            };
            const protocolsConfigure = yield ProtocolsConfigure.create(options);
            return {
                author,
                message: protocolsConfigure.message,
                dataStream,
                protocolsConfigure
            };
        });
    }
    ;
    /**
     * Generates a ProtocolsQuery message for testing.
     */
    static generateProtocolsQuery(input) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            // generate author persona if not given
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield TestDataGenerator.generatePersona();
            const authorizationSignatureInput = Jws.createSignatureInput(author);
            const options = {
                messageTimestamp: input === null || input === void 0 ? void 0 : input.messageTimestamp,
                filter: input === null || input === void 0 ? void 0 : input.filter,
                authorizationSignatureInput,
                permissionsGrantId: input === null || input === void 0 ? void 0 : input.permissionsGrantId,
            };
            removeUndefinedProperties(options);
            const protocolsQuery = yield ProtocolsQuery.create(options);
            return {
                author,
                message: protocolsQuery.message,
                protocolsQuery
            };
        });
    }
    ;
    /**
     * Generates a RecordsWrite message for testing.
     * Implementation currently uses `RecordsWrite.create()`.
     * @param input.attesters Attesters of the message. Will NOT be generated if not given.
     * @param input.data Data that belongs to the record. Generated when not given only if `dataCid` and `dataSize` are also not given.
     * @param input.dataFormat Format of the data. Defaults to 'application/json' if not given.
     * @param input.author Author of the message. Generated if not given.
     * @param input.schema Schema of the message. Randomly generated if not given.
     */
    static generateRecordsWrite(input) {
        var _a, _b, _c, _d, _e;
        return __awaiter(this, void 0, void 0, function* () {
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield TestDataGenerator.generatePersona();
            const authorizationSignatureInput = Jws.createSignatureInput(author);
            const attestationSignatureInputs = Jws.createSignatureInputs((_b = input === null || input === void 0 ? void 0 : input.attesters) !== null && _b !== void 0 ? _b : []);
            const dataCid = input === null || input === void 0 ? void 0 : input.dataCid;
            const dataSize = input === null || input === void 0 ? void 0 : input.dataSize;
            let dataBytes;
            let dataStream;
            if (dataCid === undefined && dataSize === undefined) {
                dataBytes = (_c = input === null || input === void 0 ? void 0 : input.data) !== null && _c !== void 0 ? _c : TestDataGenerator.randomBytes(32);
                dataStream = DataStream.fromBytes(dataBytes);
            }
            const options = {
                recipient: input === null || input === void 0 ? void 0 : input.recipient,
                protocol: input === null || input === void 0 ? void 0 : input.protocol,
                protocolPath: input === null || input === void 0 ? void 0 : input.protocolPath,
                contextId: input === null || input === void 0 ? void 0 : input.contextId,
                schema: (_d = input === null || input === void 0 ? void 0 : input.schema) !== null && _d !== void 0 ? _d : `http://${TestDataGenerator.randomString(20)}`,
                recordId: input === null || input === void 0 ? void 0 : input.recordId,
                parentId: input === null || input === void 0 ? void 0 : input.parentId,
                published: input === null || input === void 0 ? void 0 : input.published,
                dataFormat: (_e = input === null || input === void 0 ? void 0 : input.dataFormat) !== null && _e !== void 0 ? _e : 'application/json',
                dateCreated: input === null || input === void 0 ? void 0 : input.dateCreated,
                messageTimestamp: input === null || input === void 0 ? void 0 : input.messageTimestamp,
                datePublished: input === null || input === void 0 ? void 0 : input.datePublished,
                data: dataBytes,
                dataCid,
                dataSize,
                authorizationSignatureInput,
                attestationSignatureInputs,
                encryptionInput: input === null || input === void 0 ? void 0 : input.encryptionInput
            };
            const recordsWrite = yield RecordsWrite.create(options);
            const message = recordsWrite.message;
            return {
                author,
                message,
                dataCid,
                dataSize,
                dataBytes,
                dataStream,
                recordsWrite
            };
        });
    }
    ;
    /**
     * Generates a valid RecordsWrite that modifies the given an existing write.
     * Any mutable property is not specified will be automatically mutated.
     * e.g. if `published` is not specified, it will be toggled from the state of the given existing write.
     */
    static generateFromRecordsWrite(input) {
        var _a, _b, _c;
        return __awaiter(this, void 0, void 0, function* () {
            const existingMessage = input.existingWrite.message;
            const currentTime = getCurrentTimeInHighPrecision();
            const published = ((_a = input.published) !== null && _a !== void 0 ? _a : existingMessage.descriptor.published) ? false : true; // toggle from the parent value if not given explicitly
            const datePublished = (_b = input.datePublished) !== null && _b !== void 0 ? _b : (published ? currentTime : undefined);
            const dataBytes = (_c = input.data) !== null && _c !== void 0 ? _c : TestDataGenerator.randomBytes(32);
            const dataStream = DataStream.fromBytes(dataBytes);
            const options = {
                unsignedRecordsWriteMessage: input.existingWrite.message,
                data: dataBytes,
                published,
                datePublished,
                messageTimestamp: input.messageTimestamp,
                authorizationSignatureInput: Jws.createSignatureInput(input.author)
            };
            const recordsWrite = yield RecordsWrite.createFrom(options);
            return {
                message: recordsWrite.message,
                recordsWrite,
                dataBytes,
                dataStream
            };
        });
    }
    /**
     * Generates a RecordsQuery message for testing.
     */
    static generateRecordsQuery(input) {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            let author = input === null || input === void 0 ? void 0 : input.author;
            const anonymous = (_a = input === null || input === void 0 ? void 0 : input.anonymous) !== null && _a !== void 0 ? _a : false;
            if (anonymous && author) {
                throw new Error('Cannot have `author` and be anonymous at the same time.');
            }
            // generate author if needed
            if (author === undefined && !anonymous) {
                author = yield TestDataGenerator.generatePersona();
            }
            let authorizationSignatureInput = undefined;
            if (author !== undefined) {
                authorizationSignatureInput = Jws.createSignatureInput(author);
            }
            const options = {
                messageTimestamp: input === null || input === void 0 ? void 0 : input.messageTimestamp,
                authorizationSignatureInput,
                filter: (_b = input === null || input === void 0 ? void 0 : input.filter) !== null && _b !== void 0 ? _b : { schema: TestDataGenerator.randomString(10) },
                dateSort: input === null || input === void 0 ? void 0 : input.dateSort
            };
            removeUndefinedProperties(options);
            const recordsQuery = yield RecordsQuery.create(options);
            const message = recordsQuery.message;
            return {
                author,
                message
            };
        });
    }
    ;
    /**
     * Generates a RecordsDelete for testing.
     */
    static generateRecordsDelete(input) {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield DidKeyResolver.generate();
            const recordsDelete = yield RecordsDelete.create({
                recordId: (_b = input === null || input === void 0 ? void 0 : input.recordId) !== null && _b !== void 0 ? _b : yield TestDataGenerator.randomCborSha256Cid(),
                authorizationSignatureInput: Jws.createSignatureInput(author)
            });
            return {
                author,
                recordsDelete,
                message: recordsDelete.message
            };
        });
    }
    /**
     * Generates a HooksWrite message for testing.
     */
    static generateHooksWrite(input) {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield TestDataGenerator.generatePersona();
            const authorizationSignatureInput = Jws.createSignatureInput(author);
            const options = {
                messageTimestamp: input === null || input === void 0 ? void 0 : input.messageTimestamp,
                authorizationSignatureInput,
                filter: (_b = input === null || input === void 0 ? void 0 : input.filter) !== null && _b !== void 0 ? _b : { method: 'RecordsWrite' }, // hardcode to filter on `RecordsWrite` if no filter is given
            };
            removeUndefinedProperties(options);
            const hooksWrite = yield HooksWrite.create(options);
            return {
                author,
                message: hooksWrite.message
            };
        });
    }
    ;
    /**
     * Generates a PermissionsRequest message for testing.
     */
    static generatePermissionsRequest(input) {
        var _a, _b, _c, _d, _e, _f;
        return __awaiter(this, void 0, void 0, function* () {
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield TestDataGenerator.generatePersona();
            const permissionsRequest = yield PermissionsRequest.create({
                messageTimestamp: getCurrentTimeInHighPrecision(),
                description: input === null || input === void 0 ? void 0 : input.description,
                grantedBy: (_b = input === null || input === void 0 ? void 0 : input.grantedBy) !== null && _b !== void 0 ? _b : 'did:key:bob',
                grantedTo: (_c = input === null || input === void 0 ? void 0 : input.grantedTo) !== null && _c !== void 0 ? _c : 'did:key:alice',
                grantedFor: (_e = (_d = input === null || input === void 0 ? void 0 : input.grantedFor) !== null && _d !== void 0 ? _d : input === null || input === void 0 ? void 0 : input.grantedBy) !== null && _e !== void 0 ? _e : 'did:key:bob',
                scope: (_f = input === null || input === void 0 ? void 0 : input.scope) !== null && _f !== void 0 ? _f : {
                    interface: DwnInterfaceName.Records,
                    method: DwnMethodName.Write
                },
                conditions: input === null || input === void 0 ? void 0 : input.conditions,
                authorizationSignatureInput: Jws.createSignatureInput(author)
            });
            return {
                author,
                permissionsRequest,
                message: permissionsRequest.message
            };
        });
    }
    /**
     * Generates a PermissionsGrant message for testing.
     */
    static generatePermissionsGrant(input) {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        return __awaiter(this, void 0, void 0, function* () {
            const dateExpires = (_a = input === null || input === void 0 ? void 0 : input.dateExpires) !== null && _a !== void 0 ? _a : Temporal.Now.instant().add({ hours: 24 }).toString({ smallestUnit: 'microseconds' });
            const author = (_b = input === null || input === void 0 ? void 0 : input.author) !== null && _b !== void 0 ? _b : yield TestDataGenerator.generatePersona();
            const permissionsGrant = yield PermissionsGrant.create({
                messageTimestamp: (_c = input === null || input === void 0 ? void 0 : input.messageTimestamp) !== null && _c !== void 0 ? _c : getCurrentTimeInHighPrecision(),
                dateExpires,
                description: (_d = input === null || input === void 0 ? void 0 : input.description) !== null && _d !== void 0 ? _d : 'perms',
                grantedBy: (_e = input === null || input === void 0 ? void 0 : input.grantedBy) !== null && _e !== void 0 ? _e : author.did,
                grantedTo: (_f = input === null || input === void 0 ? void 0 : input.grantedTo) !== null && _f !== void 0 ? _f : (yield TestDataGenerator.generatePersona()).did,
                grantedFor: (_g = input === null || input === void 0 ? void 0 : input.grantedFor) !== null && _g !== void 0 ? _g : author.did,
                permissionsRequestId: input === null || input === void 0 ? void 0 : input.permissionsRequestId,
                scope: (_h = input === null || input === void 0 ? void 0 : input.scope) !== null && _h !== void 0 ? _h : {
                    interface: DwnInterfaceName.Records,
                    method: DwnMethodName.Write
                },
                conditions: input === null || input === void 0 ? void 0 : input.conditions,
                authorizationSignatureInput: Jws.createSignatureInput(author)
            });
            return {
                author,
                permissionsGrant,
                message: permissionsGrant.message
            };
        });
    }
    /**
     * Generates a PermissionsRevoke message for testing.
     */
    static generatePermissionsRevoke(input) {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield TestDataGenerator.generatePersona();
            const authorizationSignatureInput = Jws.createSignatureInput(author);
            const permissionsRevoke = yield PermissionsRevoke.create({
                authorizationSignatureInput,
                permissionsGrantId: (_b = input === null || input === void 0 ? void 0 : input.permissionsGrantId) !== null && _b !== void 0 ? _b : yield TestDataGenerator.randomCborSha256Cid(),
                messageTimestamp: input === null || input === void 0 ? void 0 : input.dateCreated
            });
            return {
                author,
                permissionsRevoke,
                message: permissionsRevoke.message
            };
        });
    }
    static generateEventsGet(input) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield TestDataGenerator.generatePersona();
            const authorizationSignatureInput = Jws.createSignatureInput(author);
            const options = { authorizationSignatureInput };
            if (input === null || input === void 0 ? void 0 : input.watermark) {
                options.watermark = input.watermark;
            }
            const eventsGet = yield EventsGet.create(options);
            return {
                author,
                eventsGet,
                message: eventsGet.message
            };
        });
    }
    static generateMessagesGet(input) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const author = (_a = input === null || input === void 0 ? void 0 : input.author) !== null && _a !== void 0 ? _a : yield TestDataGenerator.generatePersona();
            const authorizationSignatureInput = Jws.createSignatureInput(author);
            const options = {
                authorizationSignatureInput,
                messageCids: input.messageCids
            };
            const messagesGet = yield MessagesGet.create(options);
            return {
                author,
                messagesGet,
                message: messagesGet.message,
            };
        });
    }
    /**
     * Generates a random alpha-numeric string.
     */
    static randomString(length) {
        const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        // pick characters randomly
        let randomString = '';
        for (let i = 0; i < length; i++) {
            randomString += charset.charAt(Math.floor(Math.random() * charset.length));
        }
        return randomString;
    }
    ;
    /**
     * Generates a random byte array of given length.
     */
    static randomBytes(length) {
        const randomBytes = new Uint8Array(length);
        for (let i = 0; i < length; i++) {
            randomBytes[i] = Math.floor(Math.random() * 256);
        }
        return randomBytes;
    }
    ;
    /**
     * Generates a random CBOR SHA256 CID.
     */
    static randomCborSha256Cid() {
        return __awaiter(this, void 0, void 0, function* () {
            const randomBytes = TestDataGenerator.randomBytes(32);
            const randomMultihash = yield sha256.digest(randomBytes);
            const cid = yield CID.createV1(cbor.code, randomMultihash);
            return cid.toString();
        });
    }
    /**
     * Creates a mock DID resolution result for testing purposes.
     */
    static createDidResolutionResult(persona) {
        return {
            didResolutionMetadata: {},
            didDocument: {
                id: persona.did,
                verificationMethod: [{
                        controller: persona.did,
                        id: persona.keyId,
                        type: 'JsonWebKey2020',
                        publicKeyJwk: persona.keyPair.publicJwk
                    }]
            },
            didDocumentMetadata: {}
        };
    }
}
//# sourceMappingURL=test-data-generator.js.map