// Copyright 2024 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
// at your option.
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());
    });
};
// Unless required by applicable law or agreed to in writing,
// this software is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
// specific language governing permissions and limitations under
// each license.
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import * as fs from "fs-extra";
import * as crypto from "crypto";
import { CallbackSigner } from "./Signer.js";
import { Builder } from "./Builder.js";
import { Reader } from "./Reader.js";
class TestSigner {
    constructor(privateKey) {
        this.sign = (bytes) => __awaiter(this, void 0, void 0, function* () {
            const sign = crypto.createSign("SHA256");
            sign.update(bytes);
            sign.end();
            const signature = sign.sign(this.privateKey);
            return signature;
        });
        this.privateKey = crypto.createPrivateKey({
            key: privateKey,
            format: "pem",
        });
    }
}
describe("TestSigner", () => {
    it("should sign data", () => __awaiter(void 0, void 0, void 0, function* () {
        const signer = new TestSigner(yield fs.readFile("./tests/fixtures/certs/es256.pem"));
        const bytes = Buffer.from("Hello, World!");
        const signature = yield signer.sign(bytes);
        expect(signature.length).toBeGreaterThan(0);
    }));
});
describe("CallbackSigner", () => {
    const config = {
        alg: "es256",
        certs: [fs.readFileSync("./tests/fixtures/certs/es256.pub")],
        reserveSize: 10000,
        tsaUrl: "https://timestamp.digicert.com",
        tsaHeaders: [["Content-Type", "application/json"]],
        tsaBody: Buffer.from('{"test": "body"}'),
        directCoseHandling: false,
    };
    it("should create a new instance", () => {
        const signer = CallbackSigner.newSigner(config, (data) => __awaiter(void 0, void 0, void 0, function* () { return data; }));
        expect(signer).toBeDefined();
    });
    it("should sign data", () => __awaiter(void 0, void 0, void 0, function* () {
        const signer = CallbackSigner.newSigner(config, (data) => __awaiter(void 0, void 0, void 0, function* () { return data; }));
        const data = Buffer.from("test data");
        const signature = yield signer.sign(data);
        expect(signature).toBeDefined();
    }));
    it("should get algorithm", () => {
        const signer = CallbackSigner.newSigner(config, (data) => __awaiter(void 0, void 0, void 0, function* () { return data; }));
        const alg = signer.alg();
        expect(alg).toBe("es256");
    });
    it("should return certificates", () => {
        const signer = CallbackSigner.newSigner(config, (data) => __awaiter(void 0, void 0, void 0, function* () { return data; }));
        const certs = signer.certs();
        expect(Array.isArray(certs)).toBe(true);
        expect(certs.length).toBeGreaterThan(0);
    });
    it("should return reserve size", () => {
        const signer = CallbackSigner.newSigner(config, (data) => __awaiter(void 0, void 0, void 0, function* () { return data; }));
        expect(signer.reserveSize()).toBe(10000);
    });
    it("should return time authority URL when provided", () => {
        const signer = CallbackSigner.newSigner(config, (data) => __awaiter(void 0, void 0, void 0, function* () { return data; }));
        expect(signer.timeAuthorityUrl()).toBe("https://timestamp.digicert.com");
    });
    it("should return undefined for time authority URL when not provided", () => __awaiter(void 0, void 0, void 0, function* () {
        const config = {
            alg: "es256",
            certs: [yield fs.readFile("./tests/fixtures/certs/es256.pub")],
            reserveSize: 10000,
            tsaUrl: undefined,
            tsaHeaders: undefined,
            tsaBody: undefined,
            directCoseHandling: false,
        };
        const signer = CallbackSigner.newSigner(config, (data) => __awaiter(void 0, void 0, void 0, function* () { return data; }));
        expect(signer.timeAuthorityUrl()).toBeUndefined();
    }));
    it("should create valid COSE signature with buffer output", () => __awaiter(void 0, void 0, void 0, function* () {
        const testSigner = new TestSigner(yield fs.readFile("./tests/fixtures/certs/es256.pem"));
        const createRawSignatureCallback = () => {
            return (data) => __awaiter(void 0, void 0, void 0, function* () {
                // For directCoseHandling: false, return raw signature data
                // The c2pa SDK will handle COSE wrapping internally
                return yield testSigner.sign(data);
            });
        };
        // Create a simple manifest
        const manifestDefinition = {
            vendor: "test",
            claim_generator: "test-generator",
            claim_generator_info: [
                {
                    name: "c2pa_test",
                    version: "1.0.0",
                },
            ],
            title: "Test_Manifest_Buffer",
            format: "image/jpeg",
            instance_id: "5678",
            assertions: [
                {
                    label: "org.test.assertion",
                    data: { message: "Buffer test with directCoseHandling: false" },
                },
            ],
            resources: { resources: {} },
        };
        const builder = Builder.withJson(manifestDefinition);
        const source = {
            buffer: yield fs.readFile("./tests/fixtures/CA.jpg"),
            mimeType: "image/jpeg",
        };
        const config = {
            alg: "es256",
            certs: [fs.readFileSync("./tests/fixtures/certs/es256.pub")],
            reserveSize: 10000,
            tsaUrl: undefined,
            directCoseHandling: false,
        };
        const callback = createRawSignatureCallback();
        const signer = CallbackSigner.newSigner(config, callback);
        // Sign the manifest to buffer
        const dest = { buffer: null };
        yield builder.signAsync(signer, source, dest);
        // Read the signed manifest back and verify signature is valid
        const reader = yield Reader.fromAsset({
            buffer: dest.buffer,
            mimeType: "image/jpeg",
        });
        expect(reader).not.toBeNull();
        const manifestStore = reader.json();
        const activeManifest = reader.getActive();
        // If validation_status is undefined, the signature is valid
        expect(manifestStore.validation_status[0].code).toBe("signingCredential.untrusted");
        expect(manifestStore.active_manifest).not.toBeUndefined();
        expect(activeManifest === null || activeManifest === void 0 ? void 0 : activeManifest.title).toBe("Test_Manifest_Buffer");
    }));
});
