"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KNOB_HEIGHT = void 0;
const addListener_1 = require("../../../../../client/addListener");
const animation_1 = require("../../../../../client/animation/animation");
const classnames_1 = require("../../../../../client/classnames");
const debounce_1 = require("../../../../../client/debounce");
const element_1 = require("../../../../../client/element");
const click_1 = require("../../../../../client/event/pointer/click");
const pointercancel_1 = require("../../../../../client/event/pointer/pointercancel");
const pointerdown_1 = require("../../../../../client/event/pointer/pointerdown");
const pointerenter_1 = require("../../../../../client/event/pointer/pointerenter");
const pointerleave_1 = require("../../../../../client/event/pointer/pointerleave");
const pointermove_1 = require("../../../../../client/event/pointer/pointermove");
const pointerup_1 = require("../../../../../client/event/pointer/pointerup");
const resize_1 = require("../../../../../client/event/resize");
const parentElement_1 = require("../../../../../client/platform/web/parentElement");
const style_1 = require("../../../../../client/style");
const theme_1 = require("../../../../../client/theme");
const Component_1 = require("../../Div/Component");
const Component_2 = require("../../Frame/Component");
const Component_3 = require("../../Icon/Component");
const Component_4 = require("../Tooltip/Component");
exports.KNOB_HEIGHT = 35;
const DEFAULT_STYLE = {
    position: 'absolute',
    width: 'fit-content',
    height: 'fit-content',
    touchAction: 'none',
};
class Drawer extends element_1.Element {
    constructor($props, $system) {
        super($props, $system);
        this._active = false;
        this._hidden = false;
        this._hover = false;
        this._y = 0;
        this._drawer_style = () => {
            const { style = {} } = this.$props;
            return {
                ...DEFAULT_STYLE,
                top: `${this._y}px`,
                transform: this._transform(),
                ...style,
            };
        };
        this.setActive = (active) => {
            if (active) {
                if (this._active) {
                    return;
                }
                this._setActive(true);
                this.dispatchEvent('active', {});
            }
            else {
                if (!this._active) {
                    return;
                }
                this._setActive(false);
                this.dispatchEvent('inactive', {});
            }
        };
        this._transform = () => {
            const translateX = this._get_translate_x();
            return `translateX(${translateX}px)`;
        };
        this._get_translate_x = () => {
            const { $width } = this.$context;
            const { width = 0, component } = this.$props;
            let translateX = 0;
            if (this._active) {
                translateX = -Math.min(component ? width + 2 + 6 - 1 : 0, $width - exports.KNOB_HEIGHT);
            }
            if (this._hidden) {
                translateX = -translateX + 34 + 1;
            }
            return translateX;
        };
        this._setActive = (active) => {
            const { api: { window: { setTimeout }, }, } = this.$system;
            this._active = active;
            this._animate_transform(true);
            setTimeout(() => {
                this.dispatchEvent('activated', {});
            }, animation_1.ANIMATION_T_MS + 100);
        };
        this._translate = () => {
            const transform = this._transform();
            this.drawer.$element.style.transform = transform;
        };
        this._resize = () => {
            // console.log('Drawer', '_resize')
            const { $width } = this.$context;
            const { width = 0, height = exports.KNOB_HEIGHT, component } = this.$props;
            this._translate();
            if (width > $width - exports.KNOB_HEIGHT) {
                this.frame.$element.style.width = `${$width - exports.KNOB_HEIGHT - 8}px`;
                this.frame.$element.style.height = `${height + 2}px`;
                this.content.$element.style.width = component
                    ? `${$width - exports.KNOB_HEIGHT}px`
                    : '0';
                this.content.$element.style.height = `${height + 6}px`;
            }
            else {
                this.frame.$element.style.width = `${width + 2}px`;
                this.frame.$element.style.height = `${height + 2}px`;
                this.content.$element.style.width = component ? `${width + 2 + 6}px` : '0';
                this.content.$element.style.height = `${height + 2 + 6}px`;
            }
        };
        this._on_knob_click = (event) => {
            this.setActive(!this._active);
        };
        this._on_knob_pointer_enter = (event) => {
            this._hover = true;
        };
        this._on_knob_pointer_leave = (event) => {
            this._hover = false;
        };
        this._drag = false;
        this._drag_dy = 0;
        this._clamp_top = (top) => {
            const { $height } = this.$context;
            return Math.max(Math.min(top, $height - exports.KNOB_HEIGHT), 0);
        };
        this._on_knob_pointer_down = (event) => {
            // log('Drawer', '_on_knob_pointer_down')
            const { clientY, pointerId } = event;
            this._knob.setPointerCapture(pointerId);
            this._drag_dy = this._y - clientY;
            this._drag = true;
            this._drag_pointer_id = pointerId;
            const unlisten_knob = this._knob.addEventListeners([
                (0, pointermove_1.makePointerMoveListener)((event) => {
                    if (this._drag) {
                        const { pointerId } = event;
                        if (this._drag_pointer_id === pointerId) {
                            // console.log('Drawer', '_on_knob_pointer_move')
                            const { clientY } = event;
                            this._y = this._clamp_top(clientY + this._drag_dy);
                            this.drawer.$element.style.top = `${this._y}px`;
                            this.dispatchEvent('dragged', { y: this._y });
                        }
                    }
                }),
                (0, pointerup_1.makePointerUpListener)((event) => {
                    // log('Drawer', '_on_knob_pointer_up')
                    const { pointerId } = event;
                    if (this._drag_pointer_id === pointerId) {
                        this._drag = false;
                        this._knob.releasePointerCapture(pointerId);
                        unlisten_knob();
                        this.dispatchEvent('dragend', {});
                    }
                }),
                (0, pointercancel_1.makePointerCancelListener)(() => {
                    // log('Drawer', '_on_knob_pointer_cancel')
                }),
            ]);
            this.dispatchEvent('dragstart', { y: this._y });
        };
        this._on_container_resize = (0, debounce_1.debounce)(this.$system, () => {
            if (this._active) {
                this._resize();
            }
        }, 300);
        this._animate = (style, animate) => {
            var _a, _b;
            const duration = animate ? animation_1.ANIMATION_T_MS : 0;
            const fill = 'forwards';
            if (this._animation) {
                this._animation.pause();
                this._animation.commitStyles();
            }
            this._animation = (_b = (_a = this.drawer.$element).animate) === null || _b === void 0 ? void 0 : _b.call(_a, [style], {
                duration,
                fill,
            });
            this._animation.onfinish = () => {
                (0, style_1.mergeStyle)(this.drawer.$element, style);
                this._animation = undefined;
            };
        };
        this._animate_transform = (animate) => {
            // console.log('Drawer', '_animate_transform', animate)
            const transform = this._transform();
            // this._animate(
            //   {
            //     transform,
            //   },
            //   animate
            // )
            (0, style_1.mergeStyle)(this.drawer.$element, {
                transform,
                transition: (0, animation_1.ifLinearTransition)(animate, 'transform'),
            });
        };
        this.show_tooltip = () => {
            const bbox = this._knob.getBoundingClientRect();
            this._tooltip.show(bbox.x - 30 - 3, bbox.y + 4.5);
        };
        this.hide_tooltip = () => {
            this._tooltip.hide();
        };
        const { className, style = {}, icon, title, component, active = false, hidden = false, y = 0, width = 0, height = exports.KNOB_HEIGHT, shortcut, } = this.$props;
        this._active = active;
        this._hidden = hidden;
        this._y = 0;
        const { backgroundColor = 'inherit' } = style;
        const knob = new Component_3.default({
            className: 'drawer-knob',
            icon,
            active,
            style: {
                position: 'absolute',
                top: '0',
                padding: '6px',
                transform: 'translateX(-100%)',
                height: `${exports.KNOB_HEIGHT - 12 - 1}px`,
                width: `${exports.KNOB_HEIGHT - 12 - 1}px`,
                touchAction: 'none',
                // boxShadow:
                //   'inset 1px 0 0 0 currentColor, inset -1px 0 0 0 #00000000, inset 0 1px 0 0 currentColor, inset 0 -1px 0 0 currentColor',
                backgroundColor,
                cursor: 'pointer',
                borderTopLeftRadius: '3px',
                borderBottomLeftRadius: '3px',
                borderWidth: '1px 0px 1px 1px',
                borderStyle: 'solid',
                borderColor: 'currentColor',
                borderBottom: '0',
            },
            title,
        }, this.$system);
        this._knob = knob;
        const tooltip = new Component_4.default({
            shortcut,
        }, this.$system);
        this._tooltip = tooltip;
        const frame = new Component_2.default({
            className: 'drawer-frame',
            style: {
                position: 'relative',
                width: `${width + 2}px`,
                height: `${height + 2}px`,
                borderWidth: '1px',
                borderStyle: 'solid',
                borderColor: theme_1.COLOR_NONE,
                borderRadius: '1px',
                boxSizing: 'border-box',
                overflow: 'hidden',
            },
        }, this.$system);
        this.frame = frame;
        const content = new Component_1.default({
            className: 'drawer-content',
            style: {
                display: 'flex',
                width: component ? `${width + 2 + 6}px` : '0',
                height: `${height + 2 + 6}px`,
                // borderWidth: component ? '1px' : '0',
                // borderStyle: 'solid',
                // borderColor: 'currentColor',
                // boxShadow:
                //   'inset 1px 0 0 0 #00000000, inset -1px 0 0 0 currentColor, inset 0 1px 0 0 currentColor, inset 0 -1px 0 0 currentColor',
                // borderLeftColor: NONE,
                borderTop: '1px solid currentColor',
                boxSizing: 'border-box',
                borderRadius: '0px',
                borderBottomLeftRadius: '1px',
                minHeight: '35px',
                padding: component ? '3px' : '0',
                // padding: '3px',
            },
        }, this.$system);
        content.registerParentRoot(frame);
        this.content = content;
        const container = new Component_1.default({
            className: 'drawer-column',
            style: {
                width: 'fit-content',
                height: 'fit-content',
            },
        }, this.$system);
        const notch = new Component_1.default({
            className: 'drawer-knob-notch-bottom',
            style: {
                position: 'absolute',
                bottom: '0px',
                left: '-30px',
                top: '31px',
                width: '27px',
                height: '4px',
                backgroundColor: 'none',
                borderWidth: '0px 0px 1px 0px',
                borderStyle: 'solid',
                borderColor: 'currentColor',
                boxSizing: 'border-box',
                cursor: 'pointer',
            },
        }, this.$system);
        const notch0 = new Component_1.default({
            className: 'drawer-knob-notch-bottom-left',
            style: {
                position: 'absolute',
                bottom: '0px',
                left: '-35px',
                top: '31px',
                width: '5px',
                height: '4px',
                backgroundColor: 'none',
                borderWidth: '0px 0px 1px 1px',
                borderBottomLeftRadius: '3px',
                borderStyle: 'solid',
                borderColor: 'currentColor',
                boxSizing: 'border-box',
                cursor: 'pointer',
            },
        }, this.$system);
        container.addEventListener((0, click_1.makeClickListener)({
            onClick: this._on_knob_click,
        }));
        container.addEventListener((0, pointerenter_1.makePointerEnterListener)(this._on_knob_pointer_enter));
        container.addEventListener((0, pointerleave_1.makePointerLeaveListener)(this._on_knob_pointer_leave));
        container.addEventListener((0, pointerdown_1.makePointerDownListener)(this._on_knob_pointer_down));
        container.preventDefault('mousedown');
        container.preventDefault('touchdown');
        container.registerParentRoot(knob);
        container.registerParentRoot(notch);
        container.registerParentRoot(notch0);
        const column = new Component_1.default({
            className: 'drawer-column',
            style: {
                position: 'absolute',
                bottom: '0px',
                left: '0px',
                width: '4px',
                height: 'calc(100% - 38px)',
                backgroundColor: 'none',
                borderWidth: '0px 0px 1px 1px',
                borderStyle: 'solid',
                borderColor: 'currentColor',
                borderBottomLeftRadius: '3px',
                boxSizing: 'border-box',
            },
        }, this.$system);
        const row = new Component_1.default({
            className: 'drawer-row',
            style: {
                position: 'absolute',
                bottom: '0px',
                right: '0px',
                width: 'calc(100% - 3px)',
                height: '3px',
                backgroundColor: 'none',
                borderWidth: '0px 1px 0px 0px',
                borderStyle: 'solid',
                borderColor: 'currentColor',
                borderBottom: '1px solid currentColor',
                boxSizing: 'border-box',
            },
        }, this.$system);
        const notch1 = new Component_1.default({
            className: 'drawer-armpit-top-right',
            style: {
                position: 'absolute',
                left: '21px',
                bottom: '-10px',
                width: '10px',
                height: '10px',
                backgroundColor: 'none',
                borderWidth: '1px 1px 0px 0px',
                borderTopRightRadius: '3px',
                borderStyle: 'solid',
                borderColor: 'currentColor',
                boxSizing: 'border-box',
            },
        }, this.$system);
        const drawer = new Component_1.default({
            className: (0, classnames_1.classnames)('drawer', className),
            style: {
                ...DEFAULT_STYLE,
                ...style,
            },
        }, this.$system);
        this.drawer = drawer;
        drawer.registerParentRoot(container);
        drawer.registerParentRoot(content);
        drawer.registerParentRoot(column);
        drawer.registerParentRoot(row);
        notch.registerParentRoot(notch1);
        const $element = (0, parentElement_1.parentElement)($system);
        this.$element = $element;
        this.$slot = drawer.$slot;
        this.$unbundled = false;
        this.$primitive = true;
        this.setSubComponents({
            drawer,
            knob,
            content,
            column,
        });
        this.registerRoot(drawer);
        this.registerRoot(tooltip);
    }
    onPropChanged(prop, current) {
        // console.log('Drawer', 'onPropChanged', prop, current)
        if (prop === 'className') {
            this.drawer.setProp('className', current);
        }
        else if (prop === 'style') {
            const style = this._drawer_style();
            (0, style_1.applyStyle)(this.drawer.$element, style);
            const { backgroundColor = theme_1.COLOR_NONE } = style;
            this._knob.$slot['default'].$element.style.backgroundColor =
                backgroundColor;
        }
        else if (prop === 'active') {
            this.setActive(current);
        }
        else if (prop === 'y') {
            this._y = current;
            this.drawer.$element.style.top = `${this._y}px`;
        }
        else if (prop === 'width') {
            this._resize();
        }
        else if (prop === 'height') {
            this._resize();
        }
        else if (prop === 'hidden') {
            this._translate();
        }
    }
    onMount() {
        // console.log('Drawer', 'onMount')
        this._frame_listener = (0, addListener_1.addListeners)(this.$context, [
            (0, resize_1.makeResizeListener)(this._on_container_resize),
        ]);
    }
    onUnmount() {
        this._frame_listener();
    }
    show(animate) {
        // console.log('Drawer', 'show', animate)
        this._hidden = false;
        this._animate_transform(animate);
    }
    hide(animate) {
        this._hidden = true;
        this._animate_transform(animate);
    }
}
exports.default = Drawer;
//# sourceMappingURL=Component.js.map