import * as utils from "../utility/helper-functions.js";
import * as state from "../state/state.js";

const parser = new DOMParser();
const addColor = document.querySelector(".add-color");
const paletteName = document.querySelector(".palette-name");
const paletteClear = document.querySelector(".clear-palette");
const paletteSave = document.querySelector(".save-palette");
const colorPickersContainer = document.querySelector(".color-pickers-container");
const createPaletteSection = document.querySelector(".create-palette-section");
const savedPalettesSection = document.querySelector(".saved-palettes-section");

const paletteList = [];
const editingPalette = {
    status: false,
    name: ""
};

const colorPickerSrc = `
    <div class="color-picker-wrapper">
        <input type="color" class="color-picker">
        <button class="remove-color-picker delete-button">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#d84a38"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
        </button>
    </div>
`;

const getPaletteNodeSrc = (uniqueId) => {
    return `
        <li class="saved-palette">
            <span class="palette-label"></span>
            <ul class="palette-colors"></ul>
            <div class="action-buttons">
                <label for="palette-active-${uniqueId}" class="custom-check">
                    <input type="checkbox" id="palette-active-${uniqueId}" class="palette-active">
                    <span class="custom-check-icon"></span>
                </label>
                <label for="palette-default-btn-${uniqueId}" class="custom-radio">
                    <input type="radio" id="palette-default-btn-${uniqueId}" name="set-default-palette" class="palette-default">
                    <span class="custom-radio-icon"></span>
                </label>
                <button class="palette-edit edit-button">Edit</button>
                <button class="palette-delete delete-button">Delete</button>
            </div>
        </li>
    `;
};

function getPaletteList() {
    return paletteList;
}

function addPaletteToList(value) {
    if (Array.isArray(value)) {
        // Array of palettes
        paletteList.push(...value);
    } else {
        // Single palette
        paletteList.push(value);
    }
}

function clearPaletteEdit() {
    paletteName.value = "";
    editingPalette.status = false;
    editingPalette.name = "";
    switchPaletteSectionLabels(false);
    utils.removeChildElements(colorPickersContainer, 1);
}

function switchPaletteSectionLabels(isUnderEdit) {
    const title = createPaletteSection.querySelector("h2");
    if (isUnderEdit) {
        title.textContent = "Update Palette";
        paletteClear.textContent = "Cancel";
        paletteSave.textContent = "Update";
    } else {
        title.textContent = "Create New Palette";
        paletteClear.textContent = "Clear";
        paletteSave.textContent = "Save Palette";
    }
}

function createColorPickerUI(color = null) {
    const colorPickerNode = parser.parseFromString(colorPickerSrc, "text/html").body.firstChild;
    const colorPicker = colorPickerNode.querySelector(".color-picker");
    const removeColorButton = colorPickerNode.querySelector(".remove-color-picker");
    colorPickersContainer.children[0].insertAdjacentElement("afterend", colorPickerNode);

    if (color) {
        // Normalize color code
        colorPicker.style.color = color;
        colorPicker.value = utils.rgbToHex(window.getComputedStyle(colorPicker).color);
        colorPicker.style.color = "";
    } else {
        colorPicker.value = utils.getRandomColor();
    }

    removeColorButton.addEventListener("click", (e) => {
        e.target.closest(".color-picker-wrapper").remove();
    });
}

function createPaletteUI(name, colors, isActive, isDefault) {
    const paletteNode = parser.parseFromString(getPaletteNodeSrc(utils.generateUniqueId()), "text/html");
    const editPalette = paletteNode.querySelector(".palette-edit");
    const deletePalette = paletteNode.querySelector(".palette-delete");
    const activeSwitch = paletteNode.querySelector(".saved-palette .palette-active");
    const defaultSwitch = paletteNode.querySelector(".saved-palette .palette-default");
    paletteNode.querySelector(".palette-label").textContent = name;
    paletteNode.body.firstChild.setAttribute("data-palette-name", name);

    colors.forEach((color) => {
        const colorTile = document.createElement("li");
        colorTile.className = "color-tile";
        colorTile.style.backgroundColor = color;
        colorTile.title = color;
        paletteNode.querySelector(".palette-colors").appendChild(colorTile);
    });

    if (isActive) {
        activeSwitch.checked = true;
    } else {
        defaultSwitch.disabled = true;
        defaultSwitch.parentElement.title = "Inactive palettes cannot be set as default";
    }

    if (isDefault) {
        defaultSwitch.checked = true;
        activeSwitch.disabled = true;
        activeSwitch.parentElement.title = "Default palette cannot be inactive";
    }

    activeSwitch.addEventListener("change", (e) => {
        state.setUnsavedChanges(true);
        let currentPalette = paletteList.find((palette) => palette.name === name);
        let activePalettes = paletteList.filter((palette) => palette.isActive).map(palette => palette.name);
        // Only allow activating/deactivating palettes that are not default
        if (!currentPalette.isDefault) {
            if (e.target.checked) {
                currentPalette.isActive = true;
                activePalettes.push(name);
                defaultSwitch.disabled = false;
                defaultSwitch.parentElement.title = "";
            } else {
                currentPalette.isActive = false;
                activePalettes = activePalettes.filter(paletteName => paletteName !== name);
                defaultSwitch.disabled = true;
                defaultSwitch.parentElement.title = "Inactive palettes cannot be set as default";
            }
            state.updateSettingsData("palette.list", activePalettes);
        }
    });

    defaultSwitch.addEventListener("change", (e) => {
        state.setUnsavedChanges(true);
        let currentDefault = paletteList.find((palette) => palette.name === name);
        let previousDefault = paletteList.find((palette) => palette.isDefault);
        // Only allow setting a default palette if it is active
        if (e.target.checked && currentDefault.isActive) {
            currentDefault.isDefault = true;
            activeSwitch.disabled = true;
            activeSwitch.parentElement.title = "Default palette cannot be inactive";
            state.updateSettingsData("palette.defaultPalette", name);

            if (previousDefault) {
                let previousDefaultNode = document.querySelector(`[data-palette-name="${previousDefault.name}"]`);
                let previousActiveSwitch = previousDefaultNode.querySelector(".palette-active");
                previousDefault.isDefault = false;
                previousActiveSwitch.disabled = false;
                previousActiveSwitch.parentElement.title = "";
            }
        }
    });

    editPalette.addEventListener("click", (e) => {
        editingPalette.status = true;
        editingPalette.name = name;
        paletteName.value = name;
        utils.removeChildElements(colorPickersContainer, 1);
        switchPaletteSectionLabels(true);
        createPaletteSection.scrollIntoView({ behavior: "smooth", block: "center" });
        [...colors].reverse().forEach((color) => {
            createColorPickerUI(color);
        });
    });

    deletePalette.addEventListener("click", (e) => {
        state.setUnsavedChanges(true);
        clearPaletteEdit();
        let currentPalette = document.querySelector(`[data-palette-name="${name}"]`);
        currentPalette.remove();
        state.updateSettingsData(`palette.${name}`, null);
        paletteList.splice(0, paletteList.length, ...paletteList.filter((palette) => {
            return palette.name !== name;
        }));
        if (state.getSettingsData()["palette.defaultPalette"] === name) {
            state.updateSettingsData("palette.defaultPalette", null);
        }
        const activePalettes = paletteList.filter(palette => palette.isActive).map(palette => palette.name);
        if (!activePalettes.length) {
            state.updateSettingsData("palette.list", null);
        } else {
            state.updateSettingsData("palette.list", activePalettes);
        }
        if (!paletteList.length) {
            savedPalettesSection.classList.remove("visible");
        }
    });

    document.querySelector(".palette-list").prepend(paletteNode.body.firstChild);
}

addColor.addEventListener("click", (e) => {
    e.preventDefault();
    createColorPickerUI();
});

paletteClear.addEventListener("click", (e) => {
    clearPaletteEdit();
});

paletteSave.addEventListener("click", (e) => {
    const name = paletteName.value.trim();
    const isValidName = utils.checkNameValidity(name, paletteList.map(palette => palette.name), editingPalette.name);
    const hasColors = colorPickersContainer.querySelectorAll(".color-picker").length > 1;
    if (!isValidName.valid) {
        alert(isValidName.reason);
        return;
    } else if (!hasColors) {
        alert("At least one color is required in the palette");
        return;
    } else {
        state.setUnsavedChanges(true);
        const colorPickersList = colorPickersContainer.querySelectorAll(".color-picker");
        const colors = Array.from(colorPickersList).map((colorPicker => colorPicker.value));

        // Check if editing existing palette or adding new palette
        if (editingPalette.status) {
            // Remove outdated palette
            state.updateSettingsData(`palette.${editingPalette.name}`, null);
            document.querySelector(`[data-palette-name="${editingPalette.name}"]`).remove();

            // Update with latest palette data
            const paletteUnderEdit = paletteList.find((palette) => palette.name === editingPalette.name);
            paletteUnderEdit.name = name;
            paletteUnderEdit.colors = colors;
            createPaletteUI(name, colors, paletteUnderEdit.isActive, paletteUnderEdit.isDefault);
            if (state.getSettingsData()["palette.defaultPalette"] === editingPalette.name) {
                state.updateSettingsData("palette.defaultPalette", name);
            }

            editingPalette.status = false;
            editingPalette.name = "";
            switchPaletteSectionLabels(false);
        } else {
            paletteList.push({name: name, colors: colors, isActive: false, isDefault: false});
            createPaletteUI(name, colors, false, false);
            if (!savedPalettesSection.classList.contains("visible")) {
                savedPalettesSection.classList.add("visible");
            }
        }

        state.updateSettingsData(`palette.${name}`, colors);
        paletteName.value = "";
        utils.removeChildElements(colorPickersContainer, 1);
        // Scroll the newly added/edited palette into the view
        savedPalettesSection.querySelector(".saved-palette").scrollIntoView({ behavior: "smooth", block: "center" });
    }
});

export {
    savedPalettesSection,
    getPaletteList,
    addPaletteToList,
    createPaletteUI
};
