/* ===================== AUTOGENERATED SOURCE IMPORT ===================== */

import Template from "/emcJS/util/html/template/HTMLTemplate.js";

const TPL = new Template(`
    <div id="content">
        <div id="pagination-control" class="control-container">
            <emc-button id="first" icon="⭰" border-flat="right"></emc-button>
            <emc-button id="decrease" icon="🠔" border-flat="all"></emc-button>
            <input type="number" id="current">
            <emc-i18n-label id="max-text" i18n-value="of"></emc-i18n-label>
            <div id="max"></div>
            <emc-button id="increase" icon="🠖" border-flat="all"></emc-button>
            <emc-button id="last" icon="⭲" border-flat="left"></emc-button>
        </div>
        <div id="page-size-control" class="control-container">
            <emc-i18n-label id="size-text" i18n-value="Page size"></emc-i18n-label>
            <select id="size">
                <option value="0">inf</option>
            </select>
        </div>
        <div id="entries-count-control" class="control-container">
            <emc-i18n-label id="entries-text" i18n-value="Entries"></emc-i18n-label>
            <div id="entries"></div>
        </div>
        <div id="total-count-control" class="control-container">
            <emc-i18n-label id="total-text" i18n-value="Total"></emc-i18n-label>
            <div id="total"></div>
        </div>
    </div>
    
`);

import GlobalStyle from "/emcJS/util/html/template/CSSTemplate.js";

const STYLE = new GlobalStyle(`
    :host {
        display: block;
        margin: 8px;
    }
    
    #content {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        box-sizing: border-box;
        width: 100%;
        padding: 0px;
        margin: 0px;
        background-color: transparent;
        border: none;
        font-size: 1em;
        --button-border-width: var(--pagination-border-width, 2px);
        --button-border-radius: var(--pagination-border-radius, 6px);
        --button-border-color: var(--pagination-border-color, #222222);
        --button-disabled-border-color: var(--pagination-border-color, #222222);
        --button-hover-border-color: var(--pagination-border-color, #222222);
        --input-focus-color: var(--pagination-focus-color, #06b5ff);
        --button-focus-color: var(--pagination-focus-color, #06b5ff);
    }
    
    .control-container {
        display: none;
        align-items: center;
        justify-content: center;
        margin: 2px;
    }
    
    .control-container > * {
        margin: 0px;
        font-size: 1em;
    }
    
    :host([controls~="pagination"]) #pagination-control {
        display: inline-flex;
    }
    
    :host([controls~="page-size"]) #page-size-control {
        display: inline-flex;
    }
    
    :host([controls~="entries-count"]) #entries-count-control {
        display: inline-flex;
    }
    
    :host([controls~="total-count"]) #total-count-control {
        display: inline-flex;
    }
    
    #current,
    #size {
        height: 2em;
        padding: 0px 10px;
        color: var(--input-text-color, #000000);
        background-color: var(--input-back-color, #ffffff);
        background-image: var(--input-back-image, none);
        border-style: solid;
        border-width: var(--pagination-border-width, 2px);
        border-color: var(--pagination-border-color, #000000);
        font-size: 1em;
        text-align: end;
    }
    
    #current:focus,
    #size:focus {
        box-shadow: 0 0 2px 3px var(--input-focus-color, #06b5ff);
        outline: none;
        z-index: 1;
    }
    
    #current {
        appearance: textfield;
    }
    
    #current::placeholder {
        color: var(--input-placeholder-text-color, #757575);
    }
    
    #current::-webkit-outer-spin-button,
    #current::-webkit-inner-spin-button {
        appearance: none;
        margin: 0;
    }
    
    #max,
    #max-text {
        display: flex;
    }
    
    #size-text,
    #entries-text,
    #entries,
    #total-text,
    #total {
        display: flex;
    }
    
    #max-text,
    #max,
    #size-text,
    #entries-text,
    #entries,
    #total-text,
    #total {
        justify-content: center;
        align-items: center;
        width: min-content;
        height: 2em;
        padding: 0px 10px;
        color: var(--button-text-color, #000000);
        background-color: var(--button-back-color, #eaeaea);
        background-image: var(--button-back-image, none);
        border-style: solid;
        border-width: var(--pagination-border-width, 2px);
        border-color: var(--pagination-border-color, #222222);
        white-space: nowrap;
        user-select: none;
        overflow: hidden;
        font-size: 1em;
    }
    
    #size,
    #entries,
    #total {
        border-top-right-radius: var(--pagination-border-radius, 6px);
        border-bottom-right-radius: var(--pagination-border-radius, 6px);
    }
    
    #max-text {
        margin-left: calc(var(--pagination-border-width, 2px) * -1);
        margin-right: calc(var(--pagination-border-width, 2px) * -1);
    }
    
    #decrease,
    #first {
        margin-left: 0px;
        margin-right: calc(var(--pagination-border-width, 2px) * -1);
    }
    
    #increase,
    #last {
        margin-left: calc(var(--pagination-border-width, 2px) * -1);
        margin-right: 0px;
    }
    
    #size-text,
    #entries-text,
    #total-text {
        margin-left: 0px;
        margin-right: calc(var(--pagination-border-width, 2px) * -1);
        border-top-left-radius: var(--pagination-border-radius, 6px);
        border-bottom-left-radius: var(--pagination-border-radius, 6px);
    }
    
    #current:disabled {
        color: var(--button-text-color, #000000);
        background-color: var(--button-back-color, #eaeaea);
        background-image: var(--button-back-image, none);
    }
    
    #size {
        display: inline-block;
        cursor: pointer;
    }
    
    #size:disabled {
        cursor: default;
        color: var(--button-text-color, #000000);
        background-color: var(--button-back-color, #eaeaea);
        background-image: var(--button-back-image, none);
        opacity: 1;
        appearance: none;
    }
    
`);

/* ======================================================================= */

import CustomElementDelegating from "../../element/CustomElementDelegating.js";
import {debounce} from "../../../util/Debouncer.js";
import "../../i18n/I18nLabel.js";
import "../../form/button/Button.js";

// TODO add sort manager (modal with two lists, one contains available columns, the other the sort order)

/* TODO
- create component for each control
- add abstract control as base class
- controls should each be added individually
- DataViewControlToolbar as optional container (?)
*/

export default class DataViewControlToolbar extends CustomElementDelegating {

    static get controls() {
        return ["pagination", "page-size", "entries-count", "total-count"];
    }

    #firstEl;

    #decreaseEl;

    #currentEl;

    #maxEl;

    #increaseEl;

    #lastEl;

    #sizeEl;

    #entriesEl;

    #totalEl;

    #infiniteSizeOpt = document.createElement("option");

    constructor() {
        super();
        this.shadowRoot.append(TPL.generate());
        STYLE.apply(this.shadowRoot);
        /* --- */
        this.#firstEl = this.shadowRoot.getElementById("first");
        this.#decreaseEl = this.shadowRoot.getElementById("decrease");
        this.#currentEl = this.shadowRoot.getElementById("current");
        this.#entriesEl = this.shadowRoot.getElementById("entries");
        this.#maxEl = this.shadowRoot.getElementById("max");
        this.#increaseEl = this.shadowRoot.getElementById("increase");
        this.#lastEl = this.shadowRoot.getElementById("last");
        this.#sizeEl = this.shadowRoot.getElementById("size");
        this.#totalEl = this.shadowRoot.getElementById("total");
        /* --- */
        this.#firstEl.addEventListener("click", (event) => {
            event.stopPropagation();
            this.value = 0;
        });
        this.#decreaseEl.addEventListener("click", (event) => {
            event.stopPropagation();
            const currentValue = this.value;
            if (currentValue > 0) {
                this.value = currentValue - 1;
            }
        });
        this.#increaseEl.addEventListener("click", (event) => {
            event.stopPropagation();
            const currentValue = this.value;
            const maxValue = this.max;
            if (currentValue < maxValue) {
                this.value = currentValue + 1;
            }
        });
        this.#lastEl.addEventListener("click", (event) => {
            event.stopPropagation();
            const maxValue = this.max;
            this.value = maxValue;
        });
        this.#currentEl.addEventListener("change", (event) => {
            event.stopPropagation();
            this.value = this.#currentEl.value;
        });
        this.#sizeEl.addEventListener("change", (event) => {
            event.stopPropagation();
            this.size = this.#sizeEl.value;
        });
        /* --- */
        new ResizeObserver(() => {
            this.#currentEl.style.width = `${this.#maxEl.offsetWidth}px`;
        }).observe(this.#maxEl);
        /* --- */
        this.#infiniteSizeOpt.value = "0";
        this.#infiniteSizeOpt.innerText = "inf";
        this.#sizeEl.append(this.#infiniteSizeOpt);
    }

    set value(value) {
        this.setIntAttribute("value", value, 1, this.max);
    }

    get value() {
        return this.getIntAttribute("value");
    }

    set max(value) {
        this.setIntAttribute("max", value, 1);
    }

    get max() {
        return this.getIntAttribute("max");
    }

    set size(value) {
        this.setIntAttribute("size", value, 0);
    }

    get size() {
        return this.getIntAttribute("size");
    }

    set entries(value) {
        this.setIntAttribute("entries", value, 1);
    }

    get entries() {
        return this.getIntAttribute("entries");
    }

    set total(value) {
        this.setIntAttribute("total", value, 0);
    }

    get total() {
        return this.getIntAttribute("total");
    }

    set sizes(value) {
        this.setAttribute("sizes", value);
    }

    get sizes() {
        return this.getAttribute("sizes");
    }

    set controls(value) {
        this.setListAttrinute("controls", value, DataViewControlToolbar.controls);
    }

    get controls() {
        return this.getListAttrinute("controls");
    }

    addControl(control) {
        if (DataViewControlToolbar.controls.includes(control)) {
            const controls = this.controls;
            if (!controls.includes(control)) {
                this.controls = [...controls, control];
            }
        }
    }

    removeControl(control) {
        if (DataViewControlToolbar.controls.includes(control)) {
            const controls = this.controls;
            if (controls.includes(control)) {
                this.controls = controls.filter((c) => c !== control);
            }
        }
    }

    toggleControl(control, forceTo) {
        if (forceTo === true) {
            this.addControl(control);
        } else if (forceTo === false) {
            this.removeControl(control);
        } else if (DataViewControlToolbar.controls.includes(control)) {
            const controls = this.controls;
            if (controls.includes(control)) {
                this.controls = controls.filter((c) => c !== control);
            } else {
                this.controls = [...controls, control];
            }
        }
    }

    static get observedAttributes() {
        return ["value", "max", "size", "entries", "total", "sizes"];
    }

    attributeChangedCallback(name, oldValue, newValue) {
        switch (name) {
            case "value": {
                if (oldValue != newValue) {
                    const currentValue = this.value ?? 1;
                    this.#currentEl.value = currentValue;
                    const ev = new Event("page");
                    ev.data = currentValue;
                    this.dispatchEvent(ev);
                    /* --- */
                    const maxValue = this.max ?? 1;
                    this.#firstEl.disabled = currentValue === 1;
                    this.#decreaseEl.disabled = currentValue === 1;
                    this.#increaseEl.disabled = currentValue === maxValue;
                    this.#lastEl.disabled = currentValue === maxValue;
                    /* --- */
                    this.#updateEntries();
                } else {
                    this.#currentEl.value = oldValue;
                }
            } break;
            case "max": {
                if (oldValue != newValue) {
                    const maxValue = this.max ?? 1;
                    const currentValue = this.value ?? 1;
                    if (currentValue > maxValue) {
                        this.value = currentValue;
                    } else {
                        this.#firstEl.disabled = currentValue === 1;
                        this.#decreaseEl.disabled = currentValue === 1;
                        this.#increaseEl.disabled = currentValue === maxValue;
                        this.#lastEl.disabled = currentValue === maxValue;
                    }
                    if (maxValue != null && maxValue > 0) {
                        this.#maxEl.innerText = maxValue;
                        this.#currentEl.disabled = maxValue <= 1;
                    } else {
                        this.#maxEl.innerText = "1";
                        this.#currentEl.disabled = true;
                    }
                }
            } break;
            case "size": {
                if (oldValue != newValue) {
                    const pageSize = this.size;
                    if (pageSize != null && pageSize > 0) {
                        this.#sizeEl.value = pageSize;
                        const ev = new Event("size");
                        ev.data = pageSize;
                        this.dispatchEvent(ev);
                    } else {
                        this.#sizeEl.value = 0;
                        const ev = new Event("size");
                        ev.data = 0;
                        this.dispatchEvent(ev);
                    }
                    this.#updateEntries();
                }
            } break;
            case "entries": {
                if (oldValue != newValue) {
                    this.#updateEntries();
                }
            } break;
            case "total": {
                if (oldValue != newValue) {
                    const totalEntries = this.total;
                    if (totalEntries != null && totalEntries > 0) {
                        this.#totalEl.innerText = totalEntries;
                    } else {
                        this.#totalEl.innerText = "0";
                    }
                }
            } break;
            case "sizes": {
                if (oldValue != newValue) {
                    this.#fillSizes();
                }
            } break;
        }
    }

    #updateEntries = debounce(() => {
        const shownEntries = this.entries ?? 1;
        if (shownEntries != null && shownEntries > 0) {
            const pageSize = this.size;
            if (pageSize != null && pageSize > 0) {
                const currentValue = this.value ?? 1;
                const currentStart = (currentValue - 1) * pageSize;
                const currentEnd = currentStart + shownEntries;
                this.#entriesEl.innerText = `${currentStart + 1} - ${currentEnd} (${shownEntries})`;
            } else {
                this.#entriesEl.innerText = shownEntries;
            }
        } else {
            this.#entriesEl.innerText = "0";
        }
    });

    #fillSizes() {
        const sizes = this.sizes.split(",");
        this.#sizeEl.innerHTML = "";
        this.#sizeEl.append(this.#infiniteSizeOpt);
        const parsedSizes = [];
        for (const size of sizes) {
            const parsedSize = parseInt(size);
            if (!isNaN(parsedSize)) {
                parsedSizes.push(parsedSize);
            }
        }
        if (parsedSizes.length) {
            const currentPageSize = this.#sizeEl.value;
            let hasPageSize = false;
            parsedSizes.sort((a, b) => a - b);
            for (const size of parsedSizes) {
                const opt = document.createElement("option");
                opt.value = size;
                opt.innerText = size;
                this.#sizeEl.append(opt);
                if (size === currentPageSize) {
                    hasPageSize = true;
                }
            }
            if (!hasPageSize) {
                this.#sizeEl.value = parsedSizes[0];
            }
            this.#sizeEl.disabled = false;
        } else {
            this.#sizeEl.value = 0;
            this.#sizeEl.disabled = true;
        }
    }

}

customElements.define("emc-dataview-control-toolbar", DataViewControlToolbar);
