// 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.
import path from "path";
import * as fs from "fs-extra";
import sharp from "sharp";
import { Trustmark } from "./Trustmark.js";
const tempDir = path.join(__dirname, "..", "tmp");
// Helper function to convert raw RGB pixel data to JPEG format
function rawRgbToJpeg(rawRgbData, width, height) {
    return __awaiter(this, void 0, void 0, function* () {
        // Create a sharp image from raw RGB data
        const image = sharp(rawRgbData, {
            raw: {
                width,
                height,
                channels: 3, // RGB
            },
        });
        // Convert to JPEG format
        return yield image.jpeg().toBuffer();
    });
}
describe("Trustmark", () => {
    let trustmark;
    let testImage;
    let testImageWidth;
    let testImageHeight;
    const trustmarkConfig = {
        variant: "B", // Original Trustmark model
        version: "BCH_3", // Tolerates 3 bit flips
        modelPath: path.join(tempDir, "trustmark_models"), // Use temporary directory for model path
    };
    beforeAll(() => __awaiter(void 0, void 0, void 0, function* () {
        yield fs.ensureDir(tempDir);
        // Use an actual test image from fixtures directory
        testImage = yield fs.readFile("./tests/fixtures/A.jpg");
        // Get image dimensions for converting raw pixel data
        const imageInfo = yield sharp(testImage).metadata();
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        testImageWidth = imageInfo.width;
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        testImageHeight = imageInfo.height;
        trustmark = yield Trustmark.newTrustmark(trustmarkConfig);
    }));
    describe("newTrustmark", () => {
        it("should create a new trustmark instance with valid config", () => __awaiter(void 0, void 0, void 0, function* () {
            // This test will be skipped if the model file doesn't exist
            expect(trustmark).toBeDefined();
            expect(typeof trustmark.encode).toBe("function");
            expect(typeof trustmark.decode).toBe("function");
        }));
        it("should throw error with invalid config", () => __awaiter(void 0, void 0, void 0, function* () {
            const invalidConfig = {
                variant: "X", // Invalid variant
                version: "BCH_3", // Valid version
            };
            yield expect(Trustmark.newTrustmark(invalidConfig)).rejects.toThrow("Watermark configuration error: invalid variant");
        }));
    });
    describe("encode", () => {
        it("should encode a watermark into an image with default watermark", () => __awaiter(void 0, void 0, void 0, function* () {
            const strength = 0.9;
            const encodedImage = yield trustmark.encode(testImage, strength);
            expect(encodedImage).toBeDefined();
            expect(Buffer.isBuffer(encodedImage)).toBe(true);
            expect(encodedImage.length).toBeGreaterThan(0);
            // The encoded image should be different from the original
            expect(encodedImage).not.toEqual(testImage);
        }));
        it("should encode a watermark into an image with custom watermark", () => __awaiter(void 0, void 0, void 0, function* () {
            const strength = 0.95;
            const customWatermark = "0101000011001";
            const encodedImage = yield trustmark.encode(testImage, strength, customWatermark);
            expect(encodedImage).toBeDefined();
            expect(Buffer.isBuffer(encodedImage)).toBe(true);
            expect(encodedImage.length).toBeGreaterThan(0);
        }));
        it("should throw error with invalid strength values", () => __awaiter(void 0, void 0, void 0, function* () {
            yield expect(trustmark.encode(testImage, -0.1)).rejects.toThrow("Watermark configuration error: strength must be between 0.0 and 1.0");
            yield expect(trustmark.encode(testImage, 1.1)).rejects.toThrow("Watermark configuration error: strength must be between 0.0 and 1.0");
        }));
        it("should throw error with empty image buffer", () => __awaiter(void 0, void 0, void 0, function* () {
            const emptyBuffer = Buffer.alloc(0);
            yield expect(trustmark.encode(emptyBuffer, 0.5)).rejects.toThrow("The image format could not be determined");
        }));
    });
    describe("decode", () => {
        it("should decode a watermark from an encoded image", () => __awaiter(void 0, void 0, void 0, function* () {
            const strength = 0.8;
            const customWatermark = "0101000011001";
            // First encode a watermark
            const rawPixelData = yield trustmark.encode(testImage, strength, customWatermark);
            // Convert raw pixel data to JPEG format for decoding
            const encodedImage = yield rawRgbToJpeg(rawPixelData, testImageWidth, testImageHeight);
            // Then decode it
            const decodedWatermark = yield trustmark.decode(encodedImage);
            expect(decodedWatermark).toBeDefined();
            expect(typeof decodedWatermark).toBe("string");
            expect(decodedWatermark.length).toBeGreaterThan(0);
            // The decoded watermark should match the original
            expect(decodedWatermark.startsWith(customWatermark)).toBeTruthy();
        }));
        it("should decode watermark from image with generated watermark", () => __awaiter(void 0, void 0, void 0, function* () {
            const strength = 0.75;
            // Encode with default watermark
            const rawPixelData = yield trustmark.encode(testImage, strength);
            // Convert raw pixel data to JPEG format for decoding
            const encodedImage = yield rawRgbToJpeg(rawPixelData, testImageWidth, testImageHeight);
            // Decode the watermark
            const decodedWatermark = yield trustmark.decode(encodedImage);
            expect(decodedWatermark).toBeDefined();
            expect(typeof decodedWatermark).toBe("string");
            expect(decodedWatermark.length).toBeGreaterThan(0);
        }));
        it("should throw error decoding from original image (no watermark)", () => __awaiter(void 0, void 0, void 0, function* () {
            // Try to decode from an image that hasn't been watermarked
            yield expect(trustmark.decode(testImage)).rejects.toThrow("watermark is corrupt or missing");
        }));
        it("should throw error with empty image buffer", () => __awaiter(void 0, void 0, void 0, function* () {
            const emptyBuffer = Buffer.alloc(0);
            yield expect(trustmark.decode(emptyBuffer)).rejects.toThrow("The image format could not be determined");
        }));
    });
});
