import { div } from "@bokehjs/core/dom";
import { isArray } from "@bokehjs/core/util/types";
import { WidgetView } from "@bokehjs/models/widgets/widget";
import { LayoutDOM, LayoutDOMView } from "@bokehjs/models/layouts/layout_dom";
export class PanelMarkupView extends WidgetView {
    async lazy_initialize() {
        await super.lazy_initialize();
        if (this.provider.status == "not_started" || this.provider.status == "loading")
            this.provider.ready.connect(() => {
                if (this.contains_tex_string(this.model.text))
                    this.render();
            });
    }
    connect_signals() {
        super.connect_signals();
        this.connect(this.model.change, () => {
            this.render();
        });
    }
    has_math_disabled() {
        return this.model.disable_math || !this.contains_tex_string(this.model.text);
    }
    render() {
        super.render();
        set_size(this.el, this.model);
        this.container = div();
        set_size(this.container, this.model);
        this.shadow_el.appendChild(this.container);
        if (this.provider.status == "failed" || this.provider.status == "loaded")
            this._has_finished = true;
    }
}
PanelMarkupView.__name__ = "PanelMarkupView";
export function set_size(el, model) {
    let width_policy = model.width != null ? "fixed" : "fit";
    let height_policy = model.height != null ? "fixed" : "fit";
    const { sizing_mode, margin } = model;
    if (sizing_mode != null) {
        if (sizing_mode == "fixed")
            width_policy = height_policy = "fixed";
        else if (sizing_mode == "stretch_both")
            width_policy = height_policy = "max";
        else if (sizing_mode == "stretch_width")
            width_policy = "max";
        else if (sizing_mode == "stretch_height")
            height_policy = "max";
        else {
            switch (sizing_mode) {
                case "scale_width":
                    width_policy = "max";
                    height_policy = "min";
                    break;
                case "scale_height":
                    width_policy = "min";
                    height_policy = "max";
                    break;
                case "scale_both":
                    width_policy = "max";
                    height_policy = "max";
                    break;
                default:
                    throw new Error("unreachable");
            }
        }
    }
    let wm, hm;
    if (isArray(margin)) {
        if (margin.length === 4) {
            hm = margin[0] + margin[2];
            wm = margin[1] + margin[3];
        }
        else {
            hm = margin[0] * 2;
            wm = margin[1] * 2;
        }
    }
    else if (margin == null) {
        hm = wm = 0;
    }
    else {
        wm = hm = margin * 2;
    }
    if (width_policy == "fixed" && model.width)
        el.style.width = model.width + "px";
    else if (width_policy == "max")
        el.style.width = wm ? `calc(100% - ${wm}px)` : "100%";
    if (model.min_width != null)
        el.style.minWidth = model.min_width + "px";
    if (model.max_width != null)
        el.style.maxWidth = model.max_width + "px";
    if (height_policy == "fixed" && model.height)
        el.style.height = model.height + "px";
    else if (height_policy == "max")
        el.style.height = hm ? `calc(100% - ${hm}px)` : "100%";
    if (model.min_height != null)
        el.style.minHeight = model.min_height + "px";
    if (model.max_width != null)
        el.style.maxHeight = model.max_height + "px";
}
export class HTMLBoxView extends LayoutDOMView {
    connect_signals() {
        super.connect_signals();
        // Note due to on_change hack properties must be defined in this order.
        const { css_classes, stylesheets } = this.model.properties;
        this._prev_css_classes = this.model.css_classes;
        this.on_change([stylesheets], () => this.invalidate_render());
        this.on_change([css_classes], () => {
            // Note: This ensures that changes in the loading parameter in Panel
            // do NOT trigger a full re-render
            const css = [];
            let skip = false;
            for (const cls of this.model.css_classes) {
                if (cls === 'pn-loading')
                    skip = true;
                else if (skip)
                    skip = false;
                else
                    css.push(cls);
            }
            const prev = this._prev_css_classes;
            if (JSON.stringify(css) === JSON.stringify(prev))
                this.class_list.clear().add(...this.css_classes());
            else
                this.invalidate_render();
            this._prev_css_classes = css;
        });
    }
    render() {
        super.render();
        set_size(this.el, this.model);
    }
    on_change(properties, fn) {
        // HACKALERT: LayoutDOMView triggers re-renders whenever css_classes change
        // which is very expensive so we do not connect this signal and handle it
        // ourself
        const p = this.model.properties;
        if (properties.length === 2 && properties[0] === p.css_classes && properties[1] === p.stylesheets) {
            return;
        }
        super.on_change(properties, fn);
    }
    get child_models() {
        return [];
    }
}
HTMLBoxView.__name__ = "HTMLBoxView";
export class HTMLBox extends LayoutDOM {
    constructor(attrs) {
        super(attrs);
    }
}
HTMLBox.__name__ = "HTMLBox";
//# sourceMappingURL=layout.js.map