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

const stylesheetSelector = document.querySelector(".stylesheet-dropdown");
const scopeSelector = document.querySelector(".styling-scope");
const componentSelector = document.querySelector(".styling-component");
const gridThemeSelector = document.querySelector(".grid-theme-scope");

const fontFamilySelector = document.querySelector(".font-family-styling");
const fontSizeField = document.querySelector(".font-size-styling");
const textColorPicker = document.querySelector(".text-color-styling");
const backgroundColorPicker = document.querySelector(".background-color-styling");
const lineWidthField = document.querySelector(".line-width-styling");
const lineColorPicker = document.querySelector(".line-color-styling");
const lineDashPatternSelector = document.querySelector(".line-dash-pattern-styling");
const textTransformSelector = document.querySelector(".text-transform-styling");
const letterSpacingField = document.querySelector(".letter-spacing-styling");
const boldCheckbox = document.querySelector(".bold-styling");
const italicCheckbox = document.querySelector(".italic-styling");
const underlineCheckbox = document.querySelector(".underline-styling");

const removeColorButtons = document.querySelectorAll(".remove-color");

let selectedScope = "global";
let selectedComponent = "chart-background";
const styleDefinitions = {};

function updateStyleDefinitions(property, value, scope = selectedScope, component = selectedComponent) {
    if (scope === "VitaraGridChart") {
        scope = gridThemeSelector.value;
    }

    if (scope === "IBCSStandard" || scope === "IBCSWaterfall") {
        scope = "ibcs";
    }

    if (property && scope && component) {
        if (!styleDefinitions[scope]) {
            styleDefinitions[scope] = {};
        }

        if (!styleDefinitions[scope][component]) {
            styleDefinitions[scope][component] = {};
        }

        if (value === null) {
            // Delete individual style property
            delete styleDefinitions[scope][component][property];
        } else {
            // Add/update style property
            styleDefinitions[scope][component][property] = value;
        }

        const classSelectors = (scope === "global" || scope === "ibcs") ? mappings.stylePropertyMapping[component].classList.join(", ") : `.${scope} ${mappings.stylePropertyMapping[component].classList.join(", ")}`;
        const stylePropsString = utils.stringifyCssBlock(styleDefinitions[scope][component]);
        if (scope === "ibcs") {
            state.updateIBCSStylesData("editorDefinedStyles", {
                ...state.getIBCSStylesData()["editorDefinedStyles"],
                [classSelectors]: stylePropsString
            });
        } else {
            state.updateStylesData("editorDefinedStyles", {
                ...state.getStylesData()["editorDefinedStyles"],
                [classSelectors]: stylePropsString
            });
        }
    }

    // Delete all style blocks in a theme
    if (component === null) {
        delete styleDefinitions[scope];
        const filteredStyles = {};
        for (const styleRule in state.getStylesData()["editorDefinedStyles"]) {
            if (!styleRule.startsWith(`.${scope}`)) {
                filteredStyles[styleRule] = state.getStylesData()["editorDefinedStyles"][styleRule];
            }
        }
        state.updateStylesData("editorDefinedStyles", filteredStyles);
    }
}

function refreshStyleSelectors(scope = selectedScope, component = selectedComponent) {
    if (scope === "VitaraGridChart") {
        scope = gridThemeSelector.value;
    }

    if (scope === "IBCSStandard" || scope === "IBCSWaterfall") {
        scope = "ibcs";
    }

    if (styleDefinitions[scope]?.[component]?.["background-color"]) {
        backgroundColorPicker.value = utils.convertToHex(styleDefinitions[scope]?.[component]?.["background-color"]);
        backgroundColorPicker.parentElement.classList.remove("empty-color");
    } else {
        backgroundColorPicker.value = "#000000";
        backgroundColorPicker.parentElement.classList.add("empty-color");
    }

    if (styleDefinitions[scope]?.[component]?.["color"]) {
        textColorPicker.value = utils.convertToHex(styleDefinitions[scope]?.[component]?.["color"]);
        textColorPicker.parentElement.classList.remove("empty-color");
    } else {
        textColorPicker.value = "#000000";
        textColorPicker.parentElement.classList.add("empty-color");
    }

    if (styleDefinitions[scope]?.[component]?.["stroke"]) {
        lineColorPicker.value = utils.convertToHex(styleDefinitions[scope]?.[component]?.["stroke"]);
        lineColorPicker.parentElement.classList.remove("empty-color");
    } else {
        lineColorPicker.value = "#000000";
        lineColorPicker.parentElement.classList.add("empty-color");
    }

    fontFamilySelector.value = utils.stripQuotes(styleDefinitions[scope]?.[component]?.["font-family"] || fontFamilySelector.options[0].value);
    fontSizeField.value = parseInt(styleDefinitions[scope]?.[component]?.["font-size"]) || "";

    boldCheckbox.checked = styleDefinitions[scope]?.[component]?.["font-weight"] === "bold";
    italicCheckbox.checked = styleDefinitions[scope]?.[component]?.["font-style"] === "italic";
    underlineCheckbox.checked = styleDefinitions[scope]?.[component]?.["text-decoration"] === "underline";
    textTransformSelector.value = styleDefinitions[scope]?.[component]?.["text-transform"] || "none";

    lineWidthField.value = parseInt(styleDefinitions[scope]?.[component]?.["stroke-width"]) || "";
    letterSpacingField.value = parseInt(styleDefinitions[scope]?.[component]?.["letter-spacing"]) || "";

    if (lineWidthField.value && styleDefinitions[scope]?.[component]?.["stroke-dasharray"]) {
        lineDashPatternSelector.value = styleDefinitions[scope]?.[component]?.["stroke-dasharray"].split(",").map((val) => {
            return (parseInt(val.trim()) / parseInt(lineWidthField.value));
        }).join(",");
    } else {
        lineDashPatternSelector.value = styleDefinitions[scope]?.[component]?.["stroke-dasharray"] || "none";
    }

    const stylingFieldsGroup = [fontFamilySelector, fontSizeField, textColorPicker, backgroundColorPicker, lineWidthField, lineColorPicker,
                                lineDashPatternSelector, textTransformSelector, letterSpacingField, boldCheckbox, italicCheckbox, underlineCheckbox];
    stylingFieldsGroup.forEach((field) => {
        if (mappings.stylePropertyMapping[component].supportedFields.some(supportedField => field.classList.contains(supportedField))) {
            field.closest(".table-field").classList.remove("hidden");
        } else {
            field.closest(".table-field").classList.add("hidden");
        }
    });
}

function createStylingComponentSelector(stylingTarget) {
    componentSelector.options.length = 0; // Clear existing options
    for (const componentKey in mappings.stylePropertyMapping) {
        if (Object.prototype.hasOwnProperty.call(mappings.stylePropertyMapping, componentKey)) {
            if (mappings.stylePropertyMapping[componentKey].stylingTarget === stylingTarget) {
                const componentItem = document.createElement("option");
                componentItem.value = componentKey;
                componentItem.textContent = mappings.stylePropertyMapping[componentKey].name;
                componentSelector.append(componentItem);
            }
        }
    }
}

function createStylingScopeSelector(scopeTarget) {
    scopeSelector.options.length = 0;
    let selectorOptions = [];
    if (scopeTarget === "normal-stylesheet") {
        selectorOptions = Object.entries(mappings.chartClassMapping).sort(([aClass, aName], [bClass, bName]) => {
            return aName.localeCompare(bName);
        });
        selectorOptions.unshift(["global", "Global (All Charts)"]);
    } else {
        selectorOptions = Object.entries(mappings.ibcsChartMapping);
    }
    selectorOptions.forEach(([className, chartName]) => {
        const chartItem = document.createElement("option");
        chartItem.value = className;
        chartItem.textContent = chartName;
        scopeSelector.append(chartItem);
    }); 
}

stylesheetSelector.addEventListener("change", (e) => {
    const isIbcsType = e.target.value === "ibcs-stylesheet";
    const gridThemeSelectorField = gridThemeSelector.closest(".table-field");

    if (isIbcsType) {
        createStylingScopeSelector("ibcs-stylesheet");
        selectedScope = scopeSelector.value;
        gridThemeSelectorField.classList.add("hidden");
        if (selectedScope === "IBCSStandard") {
            createStylingComponentSelector("ibcs-standard-styling");
        } else {
            createStylingComponentSelector("ibcs-waterfall-styling");
        }
    } else {
        createStylingScopeSelector("normal-stylesheet");
        selectedScope = scopeSelector.value;
        if (selectedScope === "VitaraGridChart") {
            createStylingComponentSelector("grid-styling");
        } else {
            createStylingComponentSelector("highcharts-d3-styling");
        }
    }

    selectedComponent = componentSelector.value;
    refreshStyleSelectors();
});

scopeSelector.addEventListener("change", (e) => {
    selectedScope = e.target.value;
    const gridThemeSelectorField = gridThemeSelector.closest(".table-field");
    if (selectedScope === "VitaraGridChart") {
        createStylingComponentSelector("grid-styling");
        gridThemeSelectorField.classList.remove("hidden");
    } else {
        if (selectedScope === "IBCSStandard") {
            createStylingComponentSelector("ibcs-standard-styling");
        } else if (selectedScope === "IBCSWaterfall") {
            createStylingComponentSelector("ibcs-waterfall-styling");
        } else {
            createStylingComponentSelector("highcharts-d3-styling");
        }
        gridThemeSelectorField.classList.add("hidden");
    }
    selectedComponent = componentSelector.value;
    refreshStyleSelectors();
});

gridThemeSelector.addEventListener("change", (e) => {
    refreshStyleSelectors();
});

componentSelector.addEventListener("change", (e) => {
    selectedComponent = e.target.value;
    refreshStyleSelectors();
});

fontFamilySelector.addEventListener("change", (e) => {
    if (e.target.value.trim() !== "") {
        updateStyleDefinitions("font-family", utils.generateFontFamilyString([e.target.value], null, false));
    } else {
        updateStyleDefinitions("font-family", null);
    }
});

fontSizeField.addEventListener("change", (e) => {
    if (e.target.value.trim() !== "") {
        updateStyleDefinitions("font-size", `${e.target.value}px`);
    } else {
        updateStyleDefinitions("font-size", null);
    }
});

textColorPicker.addEventListener("change", (e) => {
    e.target.parentElement.classList.remove("empty-color");
    updateStyleDefinitions("color", e.target.value); // for HTML text elements
    if (selectedScope !== "VitaraGridChart") {
        updateStyleDefinitions("fill", e.target.value); // for SVG text element
    }
});

backgroundColorPicker.addEventListener("change", (e) => {
    e.target.parentElement.classList.remove("empty-color");
    updateStyleDefinitions("background-color", e.target.value); // for HTML container elements
    if (selectedScope !== "VitaraGridChart") {
        updateStyleDefinitions("fill", e.target.value); // for SVG container element
    }
});

lineColorPicker.addEventListener("change", (e) => {
    e.target.parentElement.classList.remove("empty-color");
    const isImportant = stylesheetSelector.value === "ibcs-stylesheet" || selectedComponent === "data-point";
    updateStyleDefinitions("stroke", isImportant ? `${e.target.value} !important` : e.target.value);
});

lineWidthField.addEventListener("change", (e) => {
    if (e.target.value.trim() !== "") {
        updateStyleDefinitions("stroke-width", `${e.target.value}px !important`);
        // Update line dash pattern based on new stroke width
        if (lineDashPatternSelector.value !== "none" && e.target.value > 0) {
            const calculatedPattern = lineDashPatternSelector.value.split(",").map((val) => {
                return Number(val.trim()) * e.target.value;
            }).join(",");
            updateStyleDefinitions("stroke-dasharray", calculatedPattern);
        }
    } else {
        updateStyleDefinitions("stroke-width", null);
        if (styleDefinitions[selectedScope]?.[selectedComponent]?.["stroke-dasharray"]) {
            updateStyleDefinitions("stroke-dasharray", lineDashPatternSelector.value);
        }
    }
});

lineDashPatternSelector.addEventListener("change", (e) => {
    if (e.target.value === "none") {
        updateStyleDefinitions("stroke-dasharray", null);
    } else {
        const calculatedPattern = e.target.value.split(",").map((val) => {
            return Number(val.trim()) * (parseInt(styleDefinitions[selectedScope]?.[selectedComponent]?.["stroke-width"]) || 1);
        }).join(",");
        updateStyleDefinitions("stroke-dasharray", calculatedPattern);
    }
});

textTransformSelector.addEventListener("change", (e) => {
    updateStyleDefinitions("text-transform", e.target.value);
});

letterSpacingField.addEventListener("change", (e) => {
    if (e.target.value.trim() !== "") {
        updateStyleDefinitions("letter-spacing", `${e.target.value}px`);
    } else {
        updateStyleDefinitions("letter-spacing", null);
    }
});

boldCheckbox.addEventListener("change", (e) => {
    if (e.target.checked) {
        updateStyleDefinitions("font-weight", "bold");
    } else {
        updateStyleDefinitions("font-weight", null);
    }
});

italicCheckbox.addEventListener("change", (e) => {
    if (e.target.checked) {
        updateStyleDefinitions("font-style", "italic");
    } else {
        updateStyleDefinitions("font-style", null);
    }
});

underlineCheckbox.addEventListener("change", (e) => {
    if (e.target.checked) {
        updateStyleDefinitions("text-decoration", "underline");
    } else {
        updateStyleDefinitions("text-decoration", null);
    }
});

removeColorButtons.forEach((button) => {
    button.addEventListener("click", (e) => {
        const colorField = e.target.previousElementSibling.firstElementChild;
        const classList = colorField.classList;
        colorField.value = "#000000";
        colorField.parentElement.classList.add("empty-color");
        if (classList.contains("text-color-styling")) {
            updateStyleDefinitions("color", null);
            updateStyleDefinitions("fill", null);
        } else if (classList.contains("background-color-styling")) {
            updateStyleDefinitions("background-color", null);
            updateStyleDefinitions("fill", null);            
        } else if (classList.contains("line-color-styling")) {
            updateStyleDefinitions("stroke", null);
        }
    });
});

export {
    updateStyleDefinitions,
    refreshStyleSelectors,
    createStylingScopeSelector,
    createStylingComponentSelector
};
