
$(() => {

var windowDisplayed = false;
var data = null;

const GRANT_TEXT = ["None", "Read Access", "Write Access", "Read Access (Strip meta)"];
const GRANT_ICON = ["bi-question-lg", "bi-eye", "bi-pencil", "bi-eye-slash"];
const ACCESS_ICON = ["bi-question-lg", "bi-database", "bi-envelope-at", "bi-link-45deg", "bi-people"];
const TYPE_ICON = ["bi-question-lg", "bi-diagram-2", "bi-tags", "bi-braces-asterisk", "bi-images", "bi-gear"];
const TYPE_TEXT = ["Unknown", "Single photo", "Tags", "Meta", "Everything", "Admin access"];

class ShareData {
    dbId = 0;
    typeId = "";
    typeData = "";
    typeLabel = "";
    accessToId = 0;
    accessToData = "";
    grant = 0;

    constructor(data) {
        if (data) {
            this.dbId = data.id;
            this.typeId = [ "unknown", "ldapAccount", "email", "link", "every one" ].indexOf(data.type);
            this.typeData = data.typeData;
            this.typeLabel = data.typeLabel;
            this.accessToId = [ "unknown", "item", "tag", "meta", "everything", "admin"].indexOf(data.accessTo);
            this.accessToData = data.accessToData;
            this.grant = [ "none", "read", "write", "read without meta"].indexOf(data.grant);
        }
    }

    objectify() {
        return {
            id: this.dbId,
            type: [ "unknown", "ldapAccount", "email", "link", "every one" ][this.typeId],
            typeData: this.typeData,
            typeLabel: this.typeLabel,
            accessTo: [ "unknown", "item", "tag", "meta", "everything", "admin"][this.accessToId],
            accessToData: this.accessToData,
            grant: [ "none", "read", "write", "read without meta"][this.grant]
        };
    }

    compare(b) {
        if (this.typeId != b.typeId) return b.typeId - this.typeId;
        if (this.accessToId != b.accessToId) return b.accessToId - this.accessToId;
        if (this.grant != b.grant) return b.grant - this.grant;
        return 0;
    }
}

function getData() {
    return new Promise((ok) => {
        if (data)
            return ok(data);
        $.get("/api/accessAdmin/list", {}, okData => {
            data = (okData || []).map(x => new ShareData(x)).sort((a, b) => a.compare(b));
            ok(data);
        });
    });
}

function createData(data) {
    return new Promise(ok => {
        $.ajax({
            url: "/api/accessAdmin/create",
            type: "POST",
            data: data,
            success: item => {
                ok(new ShareData(item));
            },
            error: err => ok(false),
        });
    });
}

function updateData(data) {
    return new Promise(ok => {
        $.ajax({
            url: `/api/accessAdmin/${data.dbId}`,
            type: "POST",
            data: data,
            success: allData => {
                ok(true);
            },
            error: err => ok(false),
        });
    });
}

function revokeData(dbId) {
    return new Promise(ok => {
        $.ajax({
            url: `/api/accessAdmin/${dbId}`,
            type: "DELETE",
            success: allData => {
                ok(true);
            },
            error: err => ok(false),
        });
    });
}

async function buildTypeDepandentDiv(htmlElement, data) {
    htmlElement.textContent = "";
    let input = document.createElement("input");
    input.type = "text";
    if (data.accessToId === 1) {
        input.value = data.accessToData;
        htmlElement.appendChild(input);
        let span = document.createElement("span");
        span.textContent = " (" +((await MediaStorage.Instance.getMedia(data.accessToData))?.fileName || "File not found") + ")";
        htmlElement.appendChild(span);
        input.addEventListener("change", async () => {
            span.textContent = " (" +((await MediaStorage.Instance.getMedia(input.value))?.fileName || "File not found") + ")";
        });
    }
    else if (data.accessToId === 2) {
        input.value = data.accessToData;
        htmlElement.appendChild(input);
    }
    else if (data.accessToId === 3) {
        input.value = data.accessToData;
        htmlElement.appendChild(input);
    }
    if (htmlElement.children.length) {
        input.addEventListener("change", async () => {
            data.accessToData = input.value;
            await updateData(data);
        });
    }
}

function buildShareItemHeader(htmlId, data, accordionBody) {
    let container = document.createDocumentFragment();
    let header = document.createElement("h2");
    header.className = "accordion-header";
    let headerButton = document.createElement("button");
    headerButton.className = `accordion-button bi ${ACCESS_ICON[data.typeId]}`;
    headerButton.type = "button";
    headerButton.dataset.bsToggle = "collapse";
    headerButton.dataset.bsTarget = `#${htmlId}`;
    headerButton.textContent = data.typeLabel || data.typeData;
    headerButton.ariaExpanded = false;
    headerButton.ariaControls = htmlId;
    if (data.typeId === 4)
        headerButton.textContent = "Everyone"
    let accordionBodyContainer = document.createElement("div");
    accordionBodyContainer.className = "accordion-collapse collapse row";
    accordionBodyContainer.dataset.bsParent = "#pch-share-container";
    accordionBodyContainer.id = htmlId;
    header.appendChild(headerButton);
    container.appendChild(header);
    accordionBodyContainer.appendChild(accordionBody);
    container.appendChild(accordionBodyContainer);
    return container;
}

function buildShareItemRevokeButton(data, container) {
    let deleteButtonRow = document.createElement("div");
    let deleteButtonDiv = document.createElement("div");
    let deleteButton = document.createElement("button");
    deleteButtonRow.className = "container";
    deleteButtonDiv.className = "col align-self-end";
    deleteButton.className = "btn btn-danger";
    deleteButton.textContent = "Revoke";
    deleteButtonRow.appendChild(deleteButtonDiv);
    deleteButtonDiv.appendChild(deleteButton);
    deleteButton.addEventListener("click", () => {
        revokeData(data.dbId).then(success => success && container.remove());
    });
    return deleteButtonRow;
}

function buildShareItemLinkSpecific(htmlId, data) {
    if (data.typeId === 3) { // Link type
        let typeDivRow = document.createDocumentFragment();
        let linkContainer = document.createElement("div");
        linkContainer.className = "input-group container";
        let text = document.createElement("span");
        text.className = "input-group-text bi bi-link-45deg";
        linkContainer.appendChild(text);
        let input = document.createElement("input");
        const linkHref = `${document.location.origin}/linkLogin?link=${data.typeData}`;
        input.value = linkHref;
        input.className = "form-control";
        input.type = "text";
        input.disabled = true;
        linkContainer.appendChild(input);
        let bt = document.createElement("button");
        bt.className = "btn btn-primary btn-outline-secondary";
        bt.placeholder = "Copy"
        let btContent = document.createElement("span");
        btContent.className = "bi bi-clipboard-fill";
        bt.appendChild(btContent);
        linkContainer.appendChild(bt);
        typeDivRow.appendChild(linkContainer);
        bt.addEventListener("click", () => { navigator.clipboard.writeText(linkHref); });

        linkContainer = document.createElement("div");
        linkContainer.className = "container";
        input = document.createElement("input");
        input.className = "form-control";
        input.value = data.typeLabel;
        input.type = "text";
        input.id = `${htmlId}-linkLabel`;
        let label = document.createElement("label");
        label.textContent = "Link label";
        label.className = "form-label"
        label.setAttribute("for", input.id);
        linkContainer.appendChild(label);
        linkContainer.appendChild(input);
        input.addEventListener("change", async () => {
            data.typeLabel = input.value;
            await updateData(data);
        });
        typeDivRow.appendChild(linkContainer);
        return typeDivRow;
    }
}

async function buildShareItemType(typeDepandentDiv, grantDiv, data) {
    let typeDiv = document.createElement("div");
    typeDiv.className = "dropdown container";
    typeDiv.id = `pch-share-${data.dbId}-typeDropdown`
    let button = document.createElement("button");
    button.className = "btn btn-secondary dropdown-toggle bi";
    button.classList.add(TYPE_ICON[data.accessToId]);
    button.textContent = TYPE_TEXT[data.accessToId];
    button.type = "button";
    button.setAttribute("data-bs-toggle", "dropdown");
    button.setAttribute("aria-expanded", false);
    button.id = `${typeDiv.id}-button`;
    let dropdownMenu = document.createElement("ul");
    dropdownMenu.className = "dropdown-menu";
    for (let i =1; i <= TYPE_TEXT.length; ++i) {
        let li = document.createElement("li");
        let a = document.createElement("a");
        a.className = "dropdown-item bi";
        if (i === data.accessToId)
            a.classList.add("active");
        a.href="#";
        a.classList.add(TYPE_ICON[i]);
        a.textContent = TYPE_TEXT[i];
        a.addEventListener("click", async () => {
            let dbData = await getData();
            let dataIdx = dbData.findIndex(item => item.dbId === data.dbId);
            if (dataIdx === -1 || dbData[dataIdx].accessToId === i)
                return;
            dbData[dataIdx].accessToId = i;
            button.className = "btn btn-secondary dropdown-toggle bi";
            button.textContent = TYPE_TEXT[data.accessToId];
            button.classList.add(TYPE_ICON[data.accessToId]);
            button.setAttribute("aria-expanded", false);
            dropdownMenu.classList.remove("show");
            dropdownMenu.querySelectorAll(".active").forEach(i => i.classList.remove("active"));
            a.classList.add("active");
            if (dbData[dataIdx].accessToId === 5)
                grantDiv.classList.add("hidden");
            else
                grantDiv.classList.remove("hidden");
            await buildTypeDepandentDiv(typeDepandentDiv, dbData[dataIdx]);
            await updateData(dbData[dataIdx]);
        });
        li.appendChild(a);
        dropdownMenu.appendChild(li);
    }
    typeDiv.appendChild(button);
    typeDiv.appendChild(dropdownMenu);
    await buildTypeDepandentDiv(typeDepandentDiv, data);
    return typeDiv;
}

function buildShareItemGrant(grantDiv, data) {
    grantDiv.className = "dropdown container";
    if (data.accessToId === 5)
        grantDiv.classList.add("hidden");
    grantDiv.id = `pch-share-${data.dbId}-grantDropdown`;
    let button = document.createElement("button");
    button.className = "btn btn-secondary dropdown-toggle bi";
    button.type = "button";
    button.setAttribute("data-bs-toggle", "dropdown");
    button.setAttribute("aria-expanded", false);
    button.id = `${grantDiv.id}-button`;
    button.textContent = GRANT_TEXT[data.grant];
    button.classList.add(GRANT_ICON[data.grant]);
    let dropdownMenu = document.createElement("ul");
    dropdownMenu.className = "dropdown-menu";
    for (let i =1; i <= GRANT_TEXT.length; ++i) {
        let li = document.createElement("li");
        let a = document.createElement("a");
        a.className = "dropdown-item bi";
        if (i === data.grant)
            a.classList.add("active");
        a.href="#";
        a.classList.add(GRANT_ICON[i]);
        a.textContent = GRANT_TEXT[i];
        a.addEventListener("click", async () => {
            let dbData = await getData();
            let dataIdx = dbData.findIndex(item => item.dbId === data.dbId);
            if (dataIdx === -1 || dbData[dataIdx].grant === i)
                return;
            dbData[dataIdx].grant = i;
            button.className = "btn btn-secondary dropdown-toggle bi";
            button.textContent = GRANT_TEXT[data.grant];
            button.classList.add(GRANT_ICON[data.grant]);
            button.setAttribute("aria-expanded", false);
            dropdownMenu.classList.remove("show");
            dropdownMenu.querySelectorAll(".active").forEach(i => i.classList.remove("active"));
            a.classList.add("active");
            await updateData(dbData[dataIdx]);
        });
        li.appendChild(a);
        dropdownMenu.appendChild(li);
    }
    grantDiv.appendChild(button);
    grantDiv.appendChild(dropdownMenu);
    return grantDiv;
}

async function buildShareItem(data) {
    const htmlId = `collapseShareItem${data.dbId}`;
    let container = document.createElement("li");
    container.className = "accordion-item";
    let accordionBody = document.createElement("div");
    accordionBody.className = "accordion-body";
    let typeDepandentDiv = document.createElement("div");
    typeDepandentDiv.className = "container";
    let grantDiv = document.createElement("div");

    container.appendChild(buildShareItemHeader(htmlId, data, accordionBody));
    {
        const div = buildShareItemLinkSpecific(htmlId, data);
        div && accordionBody.appendChild(div);
    }
    accordionBody.appendChild(await buildShareItemType(typeDepandentDiv, grantDiv, data));
    accordionBody.appendChild(typeDepandentDiv);
    accordionBody.appendChild(buildShareItemGrant(grantDiv, data));
    accordionBody.appendChild(buildShareItemRevokeButton(data, container));
    return container;
}

async function buildShareItems(data) {
    let container = document.createElement("ul");
    for (let i of data)
        container.appendChild(await buildShareItem(i));
    return container;
}

window.showShareUi = async () => {
    if (windowDisplayed)
        return;
    document.getElementById("pch-share-wrapper").classList.remove("hidden");
    document.Title.pushTitle("Share");
    document.body.classList.add("overlay-visible");
    const data = await getData();
    document.getElementById('pch-share-loading').classList.add("hidden");
    const container = document.getElementById('pch-share-container');
    container.innerHTML = "";
    container.appendChild(await buildShareItems(data));
    windowDisplayed = true;
}

window.closeShareUi = () => {
    if (!windowDisplayed)
        return;
    document.getElementById("pch-share-wrapper").classList.add("hidden");
    document.body.classList.remove("overlay-visible");
    windowDisplayed = false;
    data = null;
    document.Title.pop();
}

document.onClosePopinRequested(() => { window.closeShareUi(); });
document.getElementById("pch-share-closeBt").addEventListener("click", window.closeShareUi);

async function createShareData(typeId, typeData) {
    let share = new ShareData();
    share.typeId = typeId;
    share.typeData = typeData;
    share.typeLabel = "";
    share.accessToId = 0;
    share.grant = 0;
    share = await createData(share);
    data.push(share);
    return share;
}

document.getElementById("pch-share-addLdap").addEventListener("click", () => {});
document.getElementById("pch-share-addEmail").addEventListener("click", () => {});
document.getElementById("pch-share-addLink").addEventListener("click", async () => {
    if (!windowDisplayed)
        return;
    document.getElementById('pch-share-container').querySelector("ul").appendChild(await buildShareItem(await createShareData(3, crypto.randomUUID().replaceAll('-', ''))));
});
document.getElementById("pch-share-addEveryone").addEventListener("click", async () => {
    if (!windowDisplayed)
        return;
    document.getElementById('pch-share-container').querySelector("ul").appendChild(await buildShareItem(await createShareData(4, "")));
});

//setTimeout(() => LoadingTasks.push(window.showShareUi), 1500);
});

