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

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

const STYLE = new GlobalStyle(`
    * {
        box-sizing: border-box;
    }
    
    :host {
        position: relative;
        box-sizing: border-box;
    }
    
    :host([disabled]:not([disabled="false"])) {
        pointer-events: none;
    }
    
    /* scrollbar */
    ::-webkit-scrollbar {
        width: var(--scrollbar-size, 8px);
        height: var(--scrollbar-size, 8px);
    }
    
    ::-webkit-scrollbar-button {
        width: 0px;
        height: 0px;
    }
    
    ::-webkit-scrollbar-track {
        background-color: var(--scrollbar-track-color, #eeeeee);
        border-style: var(--scrollbar-track-border-style, solid);
        border-width: var(--scrollbar-track-border-width, 0px);
        border-color: var(--scrollbar-track-border-color, #00000000);
        border-radius: var(--scrollbar-track-border-radius, 0px);
    }
    
    ::-webkit-scrollbar-corner {
        background-color: var(--scrollbar-corner-color, #00000000);
        border-style: var(--scrollbar-corner-border-style, solid);
        border-width: var(--scrollbar-corner-border-width, 0px);
        border-color: var(--scrollbar-corner-border-color, #00000000);
        border-radius: var(--scrollbar-corner-border-radius, 0px);
    }
    
    ::-webkit-resizer {
        background: radial-gradient(var(--scrollbar-resizer-color, #000000) calc(var(--scrollbar-size, 8px) / 2 - 2px), transparent calc(var(--scrollbar-size, 8px) / 2 - 1px));
    }
    
    ::-webkit-scrollbar-thumb {
        background-color: var(--scrollbar-thumb-color, #cccccc);
        border-style: var(--scrollbar-thumb-border-style, solid);
        border-width: var(--scrollbar-thumb-border-width, 2px);
        border-color: var(--scrollbar-thumb-border-color, #eeeeee);
        border-radius: var(--scrollbar-thumb-border-radius, 0px);
    }
    
    ::-webkit-scrollbar-thumb:hover {
        background-color: var(--scrollbar-thumb-hover-color, #999999);
        border-style: var(--scrollbar-thumb-hover-border-style, solid);
        border-width: var(--scrollbar-thumb-hover-border-width, 2px);
        border-color: var(--scrollbar-thumb-hover-border-color, #eeeeee);
    }
    
    ::-webkit-scrollbar-thumb:active {
        background-color: var(--scrollbar-thumb-active-color, #000000);
        border-style: var(--scrollbar-thumb-active-border-style, solid);
        border-width: var(--scrollbar-thumb-active-border-width, 2px);
        border-color: var(--scrollbar-thumb-active-border-color, #eeeeee);
    }
    
    /* disabled scrollbar */
    :host([disabled]:not([disabled="false"])) ::-webkit-scrollbar-track {
        background-color: var(--scrollbar-disabled-track-color, #6a6a6a);
        border-color: var(--scrollbar-disabled-track-border-color, #00000000);
    }
    
    :host([disabled]:not([disabled="false"])) ::-webkit-scrollbar-corner {
        background-color: var(--scrollbar-disabled-corner-color, #00000000);
        border-color: var(--scrollbar-disabled-corner-border-color, #00000000);
    }
    
    :host([disabled]:not([disabled="false"])) ::-webkit-resizer {
        background: radial-gradient(var(--scrollbar-disabled-resizer-color, #757575) calc(var(--scrollbar-size, 8px) / 2 - 2px), transparent calc(var(--scrollbar-size, 8px) / 2 - 1px));
    }
    
    :host([disabled]:not([disabled="false"])) ::-webkit-scrollbar-thumb {
        background-color: var(--scrollbar-disabled-thumb-color, #757575);
        border-color: var(--scrollbar-disabled-thumb-border-color, #999999);
    }
    
`);

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

import jsonParse from "../../patches/JSONParser.js";
import {getInnerText} from "../../util/helper/ui/ExtractText.js";
import {
    scrollIntoView, scrollIntoViewIfNeeded
} from "../../util/helper/ui/Scroll.js";

export default class CustomElement extends HTMLElement {

    constructor() {
        if (new.target === CustomElement) {
            throw new Error("can not construct abstract class");
        }
        super();
        /* --- */
        this.attachShadow({
            mode: "open",
            delegatesFocus: this.constructor.delegatesFocus
        });
        STYLE.apply(this.shadowRoot);
    }

    static get delegatesFocus() {
        return false;
    }

    connectedCallback() {
        if (super.connectedCallback) {
            super.connectedCallback();
        }
    }

    disconnectedCallback() {
        if (super.disconnectedCallback) {
            super.disconnectedCallback();
        }
    }

    static get observedAttributes() {
        if (super.observedAttributes) {
            return super.observedAttributes;
        }
        return [];
    }

    attributeChangedCallback(name, oldValue, newValue) {
        if (super.attributeChangedCallback) {
            super.attributeChangedCallback(name, oldValue, newValue);
        }
    }

    getText() {
        return getInnerText(this);
    }

    setBooleanAttribute(name, value) {
        if (value == null) {
            this.removeAttribute(name);
        } else if (typeof value === "boolean") {
            if (value) {
                this.setAttribute(name, "");
            } else {
                this.removeAttribute(name);
            }
        } else {
            this.setAttribute(name, value);
        }
    }

    getBooleanAttribute(name) {
        const value = this.getAttribute(name);
        if (value == null || value === "false") {
            return false;
        }
        if (value === "" || value === "true") {
            return true;
        }
        return value;
    }

    setStringAttribute(name, value) {
        if (value == null) {
            this.removeAttribute(name);
        } else {
            this.setAttribute(name, value.toString());
        }
    }

    getStringAttribute(name) {
        return this.getAttribute(name);
    }

    setNumberAttribute(name, value, min, max) {
        const parsedValue = parseFloat(value);
        if (!isNaN(parsedValue)) {
            const parsedMin = parseFloat(min) || Number.MIN_VALUE;
            const parsedMax = parseFloat(max) || Number.MAX_VALUE;
            if (parsedMin > parsedMax) {
                throw new Error("min can't be greater than max");
            }
            if (parsedValue < parsedMin) {
                this.setAttribute(name, parsedMin);
            } else if (parsedValue > parsedMax) {
                this.setAttribute(name, parsedMax);
            } else {
                this.setAttribute(name, parsedValue);
            }
        } else {
            this.removeAttribute(name);
        }
    }

    getNumberAttribute(name) {
        const value = this.getAttribute(name);
        if (value != null) {
            const parsedValue = parseFloat(value);
            if (!isNaN(parsedValue)) {
                return parsedValue;
            }
        }
        return null;
    }

    setIntAttribute(name, value, min, max) {
        const parsedValue = parseInt(value);
        if (!isNaN(parsedValue)) {
            const parsedMin = parseInt(min) || Number.MIN_SAFE_INTEGER;
            const parsedMax = parseInt(max) || Number.MAX_SAFE_INTEGER;
            if (parsedMin > parsedMax) {
                throw new Error("min can't be greater than max");
            }
            if (parsedValue < parsedMin) {
                this.setAttribute(name, parsedMin);
            } else if (parsedValue > parsedMax) {
                this.setAttribute(name, parsedMax);
            } else {
                this.setAttribute(name, parsedValue);
            }
        } else {
            this.removeAttribute(name);
        }
    }

    getIntAttribute(name) {
        const value = this.getAttribute(name);
        if (value != null) {
            const parsedValue = parseInt(value);
            if (!isNaN(parsedValue)) {
                return parsedValue;
            }
        }
        return null;
    }

    setJSONAttribute(name, value) {
        if (value != null) {
            this.setAttribute(name, JSON.stringify(value));
        } else {
            this.removeAttribute(name);
        }
    }

    getJSONAttribute(name) {
        try {
            return jsonParse(this.getAttribute(name));
        } catch {
            return null;
        }
    }

    setListAttrinute(name, value, allowedValues) {
        if (Array.isArray(value)) {
            const acceptedValues = value.filter((val) => allowedValues.includes(val));
            this.setAttribute(name, acceptedValues.join(" "));
        } else if (allowedValues.includes(value)) {
            this.setAttribute(name, value);
        } else {
            this.removeAttribute(name);
        }
    }

    getListAttrinute(name) {
        return this.getAttribute(name).split(" ");
    }

    scrollIntoViewIfNeeded(options) {
        scrollIntoViewIfNeeded(this, options);
    }

    scrollIntoView(options) {
        scrollIntoView(this, options);
    }

}
