
$(() => {
    let fullPageMediaDisplayed = false;
    let fullPageMediaList = false;

    function serializeFileSize(size) {
        let units = [ 'o', 'Ko', 'Mo', 'Go', 'To' ];
        let idx = 0;
        while (size >= 800 && idx < units.length) {
            ++idx;
            size /= 1024;
        }
        size = Math.floor(size * 100) / 100;
        return `${size} ${units[idx]}`;
    }

    function displayMeta(key, value, isRo) {
        let li = document.createElement("li");
        let type = value?.type || null;
        let val = (value?.value !== undefined ? value.value : value);
        if (!val && val !== '')
            return null;
        if (type === 'date')
            val = val.toLocaleString();
        if (["dimension", "height", "width"].indexOf(key) >= 0)
            val += ' px';
        if (["fileSize"].indexOf(key) >= 0)
            val = serializeFileSize(val);
        if (key == 'fNumber')
            val = `f/ ${val}`;
        let keyTranslate = {
            fileSize: "File Size",
            photochamberImport: "Photochamber Imported",
            lensModel: "Lens Model",
            exposureTimeStr: "Exposure Time"
        };
        let keySpan = document.createElement('span');
        let valSpan = document.createElement('div');
        li.classList.add("row");
        keySpan.className = "metaKey col-xl-12 col-4";
        valSpan.className = "metaVal col-xl-12 col-8";
        let inputGroup = document.createElement('form');
        valSpan.appendChild(inputGroup);
        inputGroup.classList.add('input-group');
        keySpan.innerText = (keyTranslate[key] || (key[0].toUpperCase()+key.substr(1))) + ':';
        let valInput = document.createElement("input");
        valInput.classList.add("form-control");
        valInput.value = val;
        valInput.disabled = isRo;
        valInput.addEventListener('keyup', evt => evt.stopPropagation());
        valInput.addEventListener('keydown', evt => evt.stopPropagation());
        inputGroup.appendChild(valInput);
        if (!isRo) {
            let bt = document.createElement('button');
            bt.className = 'btn btn-outline-secondary';
            bt.type = 'button';
            bt.innerHTML = '<i class="bi bi-pen"></i>';
            inputGroup.appendChild(bt);
            bt.addEventListener('click', () => MediaStorage.Instance.setMetaValue(fullPageMediaDisplayed?.fixedSum || fullPageMediaList, key, valInput.value));
            inputGroup.addEventListener('submit', evt => {
                evt.preventDefault();
                MediaStorage.Instance.setMetaValue(fullPageMediaDisplayed?.fixedSum || fullPageMediaList, key, valInput.value);
            });
        }
        li.appendChild(keySpan);
        li.appendChild(valSpan);
        return li;
    }

    function displayMap(geo) {
        let jsonGeo = geo;
        try {
            geo = JSON.parse(geo);
        }
        catch(err) { return null; }
        let outerHTML = document.createElement("li");
        outerHTML.className = "row";
        let container = document.createElement("div");
        container.className = "leaflet-container container";
        outerHTML.appendChild(container);
        let innerHTML = document.createElement("div");
        container.appendChild(innerHTML);
        let map = L.map(innerHTML, { scrollWheelZoom: false }).setView(geo, 13);
        L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        }).addTo(map);
        L.marker(geo).addTo(map);
        setTimeout(function () {
            map.invalidateSize();
        }, 0);
        let a = document.createElement("a");
        a.href = `https://www.openstreetmap.org/?mlat=${geo[0]}&mlon=${geo[1]}`;
        a.target = "_blank";
        a.innerHTML = jsonGeo;
        container.appendChild(a);
        return outerHTML;
    }

    function displayMetas(metaData, isRo) {
        let metaList = document.createElement("ul");

        metaData.libraryPath = null;

        metaData.tags = metaData.fixedTags = null;

        if (metaData.exposureTime && metaData.exposureTimeStr)
            metaData.exposureTime = null;

        if (metaData.date && metaData.dateTime)
            metaData.dateTime = null;

        if (metaData.height && metaData.width) {
            metaData.dimension = { type: "string", value: `${metaData.width.value} x ${metaData.height.value}` }
            metaData.height = metaData.width = null;
        }

        for (let i of [ "date", "dimension", "height", "width", "fileSize" ]) {
            let metaItem = displayMeta(i, metaData[i], true);
            metaItem && metaList.appendChild(metaItem);
            metaData[i] = null;
        }

        for (let i of Object.keys(metaData).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))) {
            if (i === 'gpsLocation') {
                let dom = displayMap(metaData[i].value);
                dom && metaList.appendChild(dom);
                continue;
            }
            let metaItem = displayMeta(i, metaData[i], isRo || !MediaStorage.Instance.allMetaTypes[i]?.canWrite);
            metaItem && metaList.appendChild(metaItem);
        }

        if (!isRo)
            for (let i of ['geoCountry', 'geoCity', 'geoAdmin']) {
                if (!metaData[i]) {
                    let metaItem = displayMeta(i, "", false);
                    metaItem && metaList.appendChild(metaItem);
                }
            }
        return metaList;
    }

    function reloadCurrentMedia() {
        fullPageMediaDisplayed && window.displayMediaFullPage(fullPageMediaDisplayed);
    }

    function displayTags(fixedTagList, tagList, writeAccess) {
        let tagListUi = document.createElement("ul");
        tagListUi.className = "taglist";
        let createTagUiItem = (i, roTag) => {
            let uiItem = document.createElement("li");
            uiItem.className = "badge text-bg-light";
            let textItem = document.createElement("span");
            textItem.textContent = i;
            uiItem.appendChild(textItem);
            if (!roTag) {
                let btItem = document.createElement("a");
                btItem.className = "border-start bi bi-x removeBt";
                btItem.href = '#';
                btItem.addEventListener('click', async e => {
                    e.preventDefault();
                    await MediaStorage.Instance.removeTag(fullPageMediaDisplayed?.fixedSum || fullPageMediaList, i);
                    reloadCurrentMedia();
                });
                uiItem.appendChild(btItem);
            }
            tagListUi.appendChild(uiItem);
        };
        for (let i of fixedTagList)
            createTagUiItem(i, true);
        for (let i of tagList)
            createTagUiItem(i, !writeAccess);
        if (writeAccess) {
            let inputGroup = document.createElement('form');
            tagListUi.appendChild(inputGroup);
            inputGroup.classList.add('input-group');
            let valInput = document.createElement("input");
            valInput.classList.add("form-control");
            valInput.addEventListener('keyup', evt => evt.stopPropagation());
            valInput.addEventListener('keydown', evt => evt.stopPropagation());
            inputGroup.appendChild(valInput);
            let bt = document.createElement('button');
            bt.className = 'btn btn-outline-secondary';
            bt.type = 'button';
            bt.innerHTML = '<i class="bi bi-tags"></i>';
            inputGroup.appendChild(bt);
            bt.addEventListener('click', async () => { await MediaStorage.Instance.addTag(fullPageMediaDisplayed?.fixedSum || fullPageMediaList, valInput.value); reloadCurrentMedia(); });
            inputGroup.addEventListener('submit', async evt => {
                evt.preventDefault();
                await MediaStorage.Instance.addTag(fullPageMediaDisplayed?.fixedSum || fullPageMediaList, valInput.value);
                reloadCurrentMedia();
            });
        }
        return tagListUi;
    }

    function displayDownloadBt(downloadLink) {
        let bt = document.createElement("button");
        bt.type = "button";
        bt.className = "btn btn-primary";
        bt.textContent = "Download";
        bt.addEventListener("click", (evt) => {
            let link = document.createElement('a');
            link.target='_blank';
            link.setAttribute("download", "");
            link.href = downloadLink;
            link.click();
        });
        return bt;
    }

    function _displayMediaFullPage(fileName, imgUrl, metaData, downloadLink, writeAccess) {
        return new Promise(ok => {
            document.getElementById("pch-fullPagePreviewContainer").classList.add("loading");
            document.getElementById("pch-fullPageMedia-title").innerText = fileName;
            document.getElementById("pch-fullPagePreview").onceLoaded = ok;
            document.getElementById("pch-fullPagePreview").src = imgUrl ?? "";

            document.getElementById("pch-fullPageDetail").innerText = "";
            if (downloadLink)
                document.getElementById("pch-fullPageDetail").appendChild(displayDownloadBt(downloadLink));
            document.getElementById("pch-fullPageDetail").appendChild(displayTags(metaData?.fixedTags || [], metaData?.tags || [], writeAccess));
            document.getElementById("pch-fullPageDetail").appendChild(displayMetas(Object.assign({}, metaData || {}), !writeAccess));
        });
    }

    function LoadPreviousMedia() {
        let i = fullPageMediaDisplayed;
        if (!i) return;
        while (i = MediaStorage.Instance.previousMedia(i)) {
            if (window.FilterManager.match(i)) {
                window.displayMediaFullPage(i);
                break;
            }
        }
    }

    function LoadNextMedia() {
        let i = fullPageMediaDisplayed;
        if (!i) return;
        while (i = MediaStorage.Instance.nextMedia(i)) {
            if (window.FilterManager.match(i)) {
                window.displayMediaFullPage(i);
                break;
            }
        }
    }

    function CloseFullpageMedia() {
        if (fullPageMediaDisplayed !== false || fullPageMediaList)
            document.body.classList.remove("overlay-visible");
        document.getElementById("pch-fullPageMedia").classList.add("hidden");
        fullPageMediaDisplayed = false;
        history.pushState({}, '', '#');
        document.Title.pop();
    }

    window.displayMediaFullPage = function(mediaItem) {
        document.getElementById("pch-fullPageMedia").classList.remove("hidden");
        document.getElementById("pch-fullPageMedia").classList.remove("multiple");
        if (fullPageMediaDisplayed)
            document.Title.replaceTitle(mediaItem.fileName);
        else
            document.Title.pushTitle(mediaItem.fileName);
        fullPageMediaDisplayed = mediaItem ?? null;
        document.body.classList.add("overlay-visible");
        if (!mediaItem)
            return _displayMediaFullPage("Error", null, {}, null, false);
        let containerSize = document.getElementById("pch-fullPageMedia").getBoundingClientRect();
        let requestSize = mediaItem.resize(containerSize.width, containerSize.height);
        document.getElementById("pch-fullPagePreview").parentNode.style.maxWidth = "100%";
        document.getElementById("pch-fullPagePreview").parentNode.style.maxHeight = "100%";
        let meta = {
            ...mediaItem.meta,
            date: { type: 'date', value: mediaItem.getDate() } || undefined,
            filename: mediaItem.filename ? { type: 'string', value: mediaItem.fileName } : undefined,
            fixedTags: mediaItem.fixedTags,
            tags: mediaItem.tags
        };
        if (document.location.hash != `#${mediaItem.fixedSum}`)
            history.pushState({}, '', `#${mediaItem.fixedSum}`);
        const requestSizeQuery = requestSize ? `&w=${requestSize.width}&h=${requestSize.height}` : "";
        return _displayMediaFullPage(mediaItem.fileName, `${mediaItem.thumbnail}?q=6${requestSizeQuery}`, meta, `${mediaItem.original}?trim`, mediaItem.writeAccess);
    }

    function aggregateMetas(medias) {
        let meta = medias.reduce((acc, x) => {
            for (let key in x.meta) {
                acc[key] = acc[key] || x.meta[key];
                acc[key] = acc[key].value != x.meta[key].value ? "(multiple)" : x.meta[key];
            }
            return acc;
        }, {});
        delete meta.dateTime;
        if (!Number.isInteger(meta.height) || !Number.isInteger(meta.width)) {
            delete meta.height;
            delete meta.width;
        }
        return meta;
    }

    window.displayMultipleMediaFullPage = function(medias) {
        const title = "Multiple edit"; // FIXME lang ?
        fullPageMediaList = Array.from(new Set(medias.map(x => x.fixedSum)));
        document.getElementById("pch-fullPageMedia").classList.remove("hidden");
        document.getElementById("pch-fullPageMedia").classList.add("multiple");
        document.Title.pushTitle(title);
        document.body.classList.add("overlay-visible");
        document.getElementById("pch-fullPagePreview").parentNode.style.maxWidth = "100%";
        document.getElementById("pch-fullPagePreview").parentNode.style.maxHeight = "100%";
        let meta = {
            ...aggregateMetas(medias),
            fixedTags: medias.reduce((acc, x) => { x.fixedTags.forEach(tag => acc.add(tag)) ; return acc; }, new Set()),
            tags: medias.reduce((acc, x) => { x.tags.forEach(tag => acc.add(tag)) ; return acc; }, new Set()),
        };
        return _displayMediaFullPage(title, "", meta, null, true);
    }

    document.getElementById("pch-fullPageMedia-closeBt")
        .addEventListener("click", () => CloseFullpageMedia());
    document.getElementById("pch-fullPagePreview").addEventListener("load", () => {
        document.getElementById("pch-fullPagePreviewContainer").classList.remove("loading");
        let domItem = document.getElementById("pch-fullPagePreview");
        domItem.onceLoaded && domItem.onceLoaded();
        domItem.onceLoaded = null;
    });
    document.addEventListener("keydown", evt => {
        if (!fullPageMediaDisplayed)
            return;
        if (evt.keyCode === 37 || evt.keyCode === 38)
            LoadPreviousMedia();
        else if (evt.keyCode === 39 || evt.keyCode === 40)
            LoadNextMedia();
    });
    document.onClosePopinRequested(() => { CloseFullpageMedia(); });
});

