"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const node_fs_1 = require("node:fs");
const node_os_1 = require("node:os");
const node_path_1 = require("node:path");
const _chai_spec_1 = require("./_chai.spec");
const ExifTool_1 = require("./ExifTool");
const TagDescriptions_1 = require("./TagDescriptions");
after(() => (0, _chai_spec_1.end)(ExifTool_1.exiftool));
describe("TagDescriptions", function () {
    this.slow(5000);
    this.timeout(30000);
    // Tests that need fresh unloaded state for each test
    describe("loading behavior", () => {
        let descriptions;
        let testCacheDir;
        beforeEach(function () {
            testCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-test-" + (0, _chai_spec_1.randomChars)());
            (0, node_fs_1.mkdirSync)(testCacheDir, { recursive: true });
            descriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
                cacheDir: testCacheDir,
            });
        });
        afterEach(() => {
            descriptions.clear();
            if ((0, node_fs_1.existsSync)(testCacheDir)) {
                (0, node_fs_1.rmSync)(testCacheDir, { recursive: true, force: true });
            }
        });
        it("starts unloaded and loads descriptions from ExifTool", async () => {
            (0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(false);
            await descriptions.preload();
            (0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(true);
            (0, _chai_spec_1.expect)(descriptions.size).to.be.greaterThan(1000);
        });
        it("get() returns curated descriptions even when not loaded", () => {
            // Curated descriptions are available immediately without preload
            (0, _chai_spec_1.expect)(descriptions.get("DateTimeOriginal")).to.not.equal(undefined);
            // But non-curated tags require loading (use a rare tag not in CuratedDescriptions)
            (0, _chai_spec_1.expect)(descriptions.get("BitsPerSample")).to.equal(undefined);
        });
        it("getAsync() auto-loads descriptions for non-curated tags", async () => {
            (0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(false);
            // Use a non-curated tag to verify auto-loading (BitsPerSample is in ExifTool but not curated)
            const desc = await descriptions.getAsync("BitsPerSample");
            (0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(true);
            (0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
        });
        it("clear() clears the in-memory cache", async () => {
            await descriptions.preload();
            (0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(true);
            descriptions.clear();
            (0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(false);
        });
    });
    // Tests that need fresh cache directories
    describe("caching", () => {
        let descriptions;
        let testCacheDir;
        beforeEach(function () {
            testCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-test-" + (0, _chai_spec_1.randomChars)());
            (0, node_fs_1.mkdirSync)(testCacheDir, { recursive: true });
            descriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
                cacheDir: testCacheDir,
            });
        });
        afterEach(() => {
            descriptions.clear();
            if ((0, node_fs_1.existsSync)(testCacheDir)) {
                (0, node_fs_1.rmSync)(testCacheDir, { recursive: true, force: true });
            }
        });
        it("creates cache file after first load", async () => {
            await descriptions.preload();
            const files = (0, node_fs_1.readdirSync)(testCacheDir);
            (0, _chai_spec_1.expect)(files.length).to.equal(1);
            (0, _chai_spec_1.expect)(files[0]).to.match(/^tag-descriptions-.*\.json$/);
        });
        it("loads from cache on second instantiation", async () => {
            await descriptions.preload();
            const size1 = descriptions.size;
            const descriptions2 = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
                cacheDir: testCacheDir,
            });
            await descriptions2.preload();
            (0, _chai_spec_1.expect)(descriptions2.size).to.equal(size1);
        });
        it("respects disableDiskCache option", async () => {
            const noCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-nocache-" + (0, _chai_spec_1.randomChars)());
            (0, node_fs_1.mkdirSync)(noCacheDir, { recursive: true });
            try {
                const noCacheDescriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
                    cacheDir: noCacheDir,
                    disableDiskCache: true,
                });
                await noCacheDescriptions.preload();
                const files = (0, node_fs_1.readdirSync)(noCacheDir);
                (0, _chai_spec_1.expect)(files.length).to.equal(0);
            }
            finally {
                (0, node_fs_1.rmSync)(noCacheDir, { recursive: true, force: true });
            }
        });
    });
    // Tests that just need loaded data - share one instance
    describe("with loaded descriptions", () => {
        let descriptions;
        let testCacheDir;
        before(async function () {
            testCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-test-" + (0, _chai_spec_1.randomChars)());
            (0, node_fs_1.mkdirSync)(testCacheDir, { recursive: true });
            descriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
                cacheDir: testCacheDir,
            });
        });
        after(() => {
            descriptions.clear();
            if ((0, node_fs_1.existsSync)(testCacheDir)) {
                (0, node_fs_1.rmSync)(testCacheDir, { recursive: true, force: true });
            }
        });
        it("preload() is idempotent", async () => {
            await descriptions.preload();
            const size1 = descriptions.size;
            await descriptions.preload();
            (0, _chai_spec_1.expect)(descriptions.size).to.equal(size1);
        });
        it("getAsync() returns curated descriptions for important tags", async () => {
            const desc = await descriptions.getAsync("DateTimeOriginal");
            (0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
            (0, _chai_spec_1.expect)(desc.desc).to.include("photo was taken");
            (0, _chai_spec_1.expect)(desc.see).to.include("exiftool.org");
        });
        it("get() returns ExifTool descriptions for standard tags", async () => {
            const desc = await descriptions.getAsync("ImageWidth");
            (0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
            (0, _chai_spec_1.expect)(desc.desc.length).to.be.greaterThan(0);
        });
        it("getAsync() returns undefined for unknown tags", async () => {
            (0, _chai_spec_1.expect)(await descriptions.getAsync("NotARealTagName12345")).to.equal(undefined);
        });
        it("get() returns undefined for unknown tags", async () => {
            await descriptions.preload();
            (0, _chai_spec_1.expect)(descriptions.get("NotARealTagName12345")).to.equal(undefined);
        });
        it("getAll() returns all descriptions", async () => {
            const all = await descriptions.getAll();
            (0, _chai_spec_1.expect)(all.size).to.be.greaterThan(1000);
            (0, _chai_spec_1.expect)(all.get("DateTimeOriginal")).to.not.equal(undefined);
        });
        it("decodes XML entities without double-unescaping", async () => {
            const all = await descriptions.getAll();
            for (const [tag, info] of all) {
                (0, _chai_spec_1.expect)(info.desc, `${tag} has undecoded entity`).to.not.match(/&(?:lt|gt|amp|quot|apos);/);
            }
        });
        // Curated description tests - verify our curated descriptions are used
        const curatedTags = [
            "DateTimeOriginal",
            "CreateDate",
            "ModifyDate",
            "Copyright",
            "Description",
            "Keywords",
            "Rating",
            "Orientation",
            "GPSLatitudeRef",
            "GPSLongitudeRef",
            "Make",
            "Model",
            "ISO",
        ];
        for (const tag of curatedTags) {
            it(`getAsync has curated description for ${tag}`, async () => {
                const desc = await descriptions.getAsync(tag);
                (0, _chai_spec_1.expect)(desc, `Missing description for ${tag}`).to.not.equal(undefined);
                (0, _chai_spec_1.expect)(desc.desc.length).to.be.greaterThan(50);
            });
        }
    });
    describe("non-English language", () => {
        let descriptions;
        let testCacheDir;
        before(async function () {
            testCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-test-de-" + (0, _chai_spec_1.randomChars)());
            (0, node_fs_1.mkdirSync)(testCacheDir, { recursive: true });
            descriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
                cacheDir: testCacheDir,
                language: "de",
            });
            await descriptions.preload();
        });
        after(() => {
            descriptions.clear();
            if ((0, node_fs_1.existsSync)(testCacheDir)) {
                (0, node_fs_1.rmSync)(testCacheDir, { recursive: true, force: true });
            }
        });
        it("uses ExifTool descriptions instead of curated ones for non-English", async () => {
            const desc = await descriptions.getAsync("DateTimeOriginal");
            (0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
            // Our curated description contains "photo was taken" - ExifTool's German one won't
            (0, _chai_spec_1.expect)(desc.desc).to.not.include("photo was taken");
            // Should have some German description from ExifTool
            (0, _chai_spec_1.expect)(desc.desc.length).to.be.greaterThan(0);
        });
        it("get() also uses ExifTool descriptions for non-English", () => {
            const desc = descriptions.get("DateTimeOriginal");
            (0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
            (0, _chai_spec_1.expect)(desc.desc).to.not.include("photo was taken");
        });
        it("does not include 'see' URLs from curated descriptions", async () => {
            const desc = await descriptions.getAsync("DateTimeOriginal");
            (0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
            // Our curated descriptions have 'see' URLs, ExifTool's don't
            (0, _chai_spec_1.expect)(desc.see).to.equal(undefined);
        });
    });
});
//# sourceMappingURL=TagDescriptions.spec.js.map