# Source: widgets/basic_widget.js

    import Component from "../components/component.js";
    import froca from "../services/froca.js";
    import { t } from "../services/i18n.js";
    import toastService from "../services/toast.js";

    /**
     * This is the base widget for all other widgets.
     *
     * For information on using widgets, see the tutorial {@tutorial widget_basics}.
     */
    class BasicWidget extends Component {
        constructor() {
            super();

            this.attrs = {
                style: ''
            };
            this.classes = [];

            this.children = [];
            this.childPositionCounter = 10;
        }

        child(...components) {
            if (!components) {
                return this;
            }

            super.child(...components);

            for (const component of components) {
                if (component.position === undefined) {
                    component.position = this.childPositionCounter;
                    this.childPositionCounter += 10;
                }
            }

            this.children.sort((a, b) => a.position - b.position);

            return this;
        }

        /**
         * Conditionally adds the given components as children to this component.
         *
         * @param {boolean} condition whether to add the components.
         * @param  {...any} components the components to be added as children to this component provided the condition is truthy.
         * @returns self for chaining.
         */
        optChild(condition, ...components) {
            if (condition) {
                return this.child(...components);
            } else {
                return this;
            }
        }

        id(id) {
            this.attrs.id = id;
            return this;
        }

        class(className) {
            this.classes.push(className);
            return this;
        }

        /**
         * Sets the CSS attribute of the given name to the given value.
         *
         * @param {string} name the name of the CSS attribute to set (e.g. `padding-left`).
         * @param {string} value the value of the CSS attribute to set (e.g. `12px`).
         * @returns self for chaining.
         */
        css(name, value) {
            this.attrs.style += `${name}: ${value};`;
            return this;
        }

        /**
         * Sets the CSS attribute of the given name to the given value, but only if the condition provided is truthy.
         *
         * @param {boolean} condition `true` in order to apply the CSS, `false` to ignore it.
         * @param {string} name the name of the CSS attribute to set (e.g. `padding-left`).
         * @param {string} value the value of the CSS attribute to set (e.g. `12px`).
         * @returns self for chaining.
         */
        optCss(condition, name, value) {
            if (condition) {
                return this.css(name, value);
            }

            return this;
        }

        contentSized() {
            this.css("contain", "none");

            return this;
        }

        collapsible() {
            this.css('min-height', '0');
            this.css('min-width', '0');
            return this;
        }

        filling() {
            this.css('flex-grow', '1');
            return this;
        }

        /**
         * Accepts a string of CSS to add with the widget.
         * @param {string} block
         * @returns {this} for chaining
         */
        cssBlock(block) {
            this.cssEl = block;
            return this;
        }

        render() {
            try {
                this.doRender();
            } catch (e) {
                this.logRenderingError(e);
            }

            this.$widget.attr('data-component-id', this.componentId);
            this.$widget
                .addClass('component')
                .prop('component', this);

            if (!this.isEnabled()) {
                this.toggleInt(false);
            }

            if (this.cssEl) {
                const css = this.cssEl.trim().startsWith('<style>') ? this.cssEl : `<style>${this.cssEl}</style>`;

                this.$widget.append(css);
            }

            for (const key in this.attrs) {
                if (key === 'style') {
                    if (this.attrs[key]) {
                        let style = this.$widget.attr('style');
                        style = style ? `${style}; ${this.attrs[key]}` : this.attrs[key];

                        this.$widget.attr(key, style);
                    }
                }
                else {
                    this.$widget.attr(key, this.attrs[key]);
                }
            }

            for (const className of this.classes) {
                this.$widget.addClass(className);
            }

            return this.$widget;
        }

        logRenderingError(e) {
            console.log("Got issue in widget ", this);
            console.error(e);

            let noteId = this._noteId;
            if (this._noteId) {
                froca.getNote(noteId, true).then((note) => {
                    toastService.showPersistent({
                        title: t("toast.widget-error.title"),
                        icon: "alert",
                        message: t("toast.widget-error.message-custom", {
                            id: noteId,
                            title: note.title,
                            message: e.message
                        })
                    });
                });
                return;
            }

            toastService.showPersistent({
                title: t("toast.widget-error.title"),
                icon: "alert",
                message: t("toast.widget-error.message-unknown", {
                    message: e.message
                })
            });
        }

        /**
         * Indicates if the widget is enabled. Widgets are enabled by default. Generally setting this to `false` will cause the widget not to be displayed, however it will still be available on the DOM but hidden.
         * @returns whether the widget is enabled.
         */
        isEnabled() {
            return true;
        }

        /**
         * Method used for rendering the widget.
         *
         * Your class should override this method.
         * The method is expected to create a this.$widget containing jQuery object
         */
        doRender() {}

        toggleInt(show) {
            this.$widget.toggleClass('hidden-int', !show);
        }

        isHiddenInt() {
            return this.$widget.hasClass('hidden-int');
        }

        toggleExt(show) {
            this.$widget.toggleClass('hidden-ext', !show);
        }

        isHiddenExt() {
            return this.$widget.hasClass('hidden-ext');
        }

        canBeShown() {
            return !this.isHiddenInt() && !this.isHiddenExt();
        }

        isVisible() {
            return this.$widget.is(":visible");
        }

        getPosition() {
            return this.position;
        }

        remove() {
            if (this.$widget) {
                this.$widget.remove();
            }
        }

        getClosestNtxId() {
            if (this.$widget) {
                return this.$widget.closest("[data-ntx-id]").attr("data-ntx-id");
            }
            else {
                return null;
            }
        }

        cleanup() {}
    }

    export default BasicWidget;