"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_STYLE = exports.TRANSCEND_PULL_DY = exports.TRANSCEND_BORDER_RADIUS = exports.TRANSCEND_HEIGHT = exports.TRANSCEND_WIDTH = void 0;
const addListener_1 = require("../../../../../client/addListener");
const ANIMATION_C_1 = require("../../../../../client/animation/ANIMATION_C");
const ANIMATION_T_S_1 = require("../../../../../client/animation/ANIMATION_T_S");
const mergeStyle_1 = require("../../../../../client/component/mergeStyle");
const element_1 = require("../../../../../client/element");
const constants_1 = require("../../../../../client/event/pointer/constants");
const pointerdown_1 = require("../../../../../client/event/pointer/pointerdown");
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 whenInteracted_1 = require("../../../../../client/whenInteracted");
const f_1 = require("../../../../core/relation/Clamp/f");
const Component_1 = require("../../Div/Component");
const Component_2 = require("../../Icon/Component");
exports.TRANSCEND_WIDTH = 33;
exports.TRANSCEND_HEIGHT = exports.TRANSCEND_WIDTH;
exports.TRANSCEND_BORDER_RADIUS = exports.TRANSCEND_WIDTH / 2;
exports.TRANSCEND_PULL_DY = exports.TRANSCEND_HEIGHT / 2;
exports.DEFAULT_STYLE = {
    position: 'absolute',
    top: '0px',
    left: '50%',
    transform: 'translateX(-50%)',
    width: `${exports.TRANSCEND_WIDTH}px`,
    height: `${exports.TRANSCEND_HEIGHT}px`,
    borderWidth: '1px',
    borderStyle: 'solid',
    borderColor: 'currentColor',
    borderBottomLeftRadius: `${exports.TRANSCEND_BORDER_RADIUS}px`,
    borderBottomRightRadius: `${exports.TRANSCEND_BORDER_RADIUS}px`,
    cursor: 'pointer',
    display: 'flex',
    justifyContent: 'center',
    touchAction: 'none',
    alignItems: 'center',
    zIndex: '1',
    // borderTop: 'none',
    marginTop: '-4px',
    // transition: 'top ${ANIMATION_T_S}s linear',
    transition: `opacity ${ANIMATION_T_S_1.ANIMATION_T_S}s linear`,
};
class Transcend extends element_1.Element {
    constructor($props, $system) {
        super($props, $system);
        this._x = 0;
        this._y = 0;
        this._y_target = 0;
        this._pull_tick_count = 0;
        this._hidden = true;
        this._down = false;
        this._get_style_left = () => {
            return `calc(50% + ${this._x + 3}px)`;
        };
        this._get_style = () => {
            const { style } = this.$props;
            const left = this._get_style_left();
            let top;
            let height = `${exports.TRANSCEND_HEIGHT}px`;
            if (this._y > 0) {
                top = `${0}px`;
                height = `${exports.TRANSCEND_HEIGHT + this._y}px`;
            }
            else {
                top = `${this._y}px`;
            }
            return {
                ...exports.DEFAULT_STYLE,
                ...style,
                left,
                top,
                height,
            };
        };
        this._refresh_style = () => {
            // console.log('Transcend', '_refresh_style')
            const style = this._get_style();
            this._container.setProp('style', style);
        };
        this._cancel_pull_tick_frame = () => {
            const { api: { animation: { cancelAnimationFrame }, }, } = this.$system;
            cancelAnimationFrame(this._pull_tick_frame);
            this._pull_tick_frame = undefined;
        };
        this._pull_tick = () => {
            const { api: { animation: { requestAnimationFrame, cancelAnimationFrame }, }, } = this.$system;
            this._pull_tick_count++;
            if (this._pointer_down_id) {
                if (this._pull_tick_count === 4 * constants_1.LONG_CLICK_TIMEOUT) {
                    this._pull_tick_count = 0;
                    this._container.releasePointerCapture(this._pointer_down_id);
                    this._pointer_down_id = undefined;
                    this._pull_tick_frame = undefined;
                    this.dispatchEvent('transcend', {}, true);
                }
                else {
                    this._pull_tick_frame = requestAnimationFrame(this._pull_tick);
                }
            }
        };
        this._start_pull_timer = () => {
            this._pull_tick();
        };
        this._translate = (x, y) => {
            const { $width } = this.$context;
            if ($width === 0) {
                return;
            }
            this._x = (0, f_1.clamp)(x, exports.TRANSCEND_WIDTH / 2 - $width / 2 + 0, $width / 2 - exports.TRANSCEND_WIDTH / 2 - 3 - 3);
            this._y = y;
            this._refresh_style();
        };
        this._on_context_resize = ({ width, height, }) => {
            // console.log('Transcend', '_on_context_resize', width, height)
            this._translate(this._x, this._y);
        };
        this._animate_y = (target_y) => {
            const { api: { animation: { requestAnimationFrame, cancelAnimationFrame }, }, } = this.$system;
            this._y_target = target_y;
            if (this._y_animation) {
                cancelAnimationFrame(this._y_animation);
            }
            const dy0 = this._y_target - this._y;
            const k = ((dy0 / 12) * ANIMATION_T_S_1.ANIMATION_T_S) / 0.2;
            const anim = () => {
                const dy = this._y_target - this._y;
                const k = dy / (6 * ANIMATION_C_1.ANIMATION_C);
                if (Math.abs(dy) >= 1) {
                    this._y += k;
                    this._y_animation = requestAnimationFrame(anim);
                }
                else {
                    this._y = this._y_target;
                }
                (0, mergeStyle_1.mergePropStyle)(this._container, {
                    top: `${this._y}px`,
                });
            };
            this._y_animation = requestAnimationFrame(anim);
        };
        const { style = {}, down = false, hidden = true } = this.$props;
        const icon = new Component_2.default({
            icon: 'chevron-up',
            style: {
                transform: down
                    ? `rotate3d(1, 0, 0, 180deg)`
                    : `rotate3d(1, 0, 0, 0deg)`,
                width: '24px',
                height: '24px',
                alignSelf: 'end',
                marginBottom: '4px',
            },
        }, this.$system);
        this._icon = icon;
        this._hidden = hidden;
        const left = this._get_style_left();
        this._y = this._hidden ? -exports.TRANSCEND_HEIGHT : 0;
        const container = new Component_1.default({
            style: {
                ...exports.DEFAULT_STYLE,
                ...style,
                left,
                y: `${-exports.TRANSCEND_HEIGHT}px`,
            },
            title: 'transcend',
        }, this.$system);
        container.preventDefault('mousedown');
        container.preventDefault('touchdown');
        container.registerParentRoot(icon);
        container.addEventListeners([
            (0, pointerdown_1.makePointerDownListener)(({ pointerId, clientX, clientY: _clientY }) => {
                // log('Transcend', '_on_pointer_down')
                let _clientX = clientX - this._x;
                container.setPointerCapture(pointerId);
                this._pointer_down_id = pointerId;
                const unlisten = container.addEventListeners([
                    (0, pointermove_1.makePointerMoveListener)(({ clientX, clientY }) => {
                        const _dy = clientY - _clientY;
                        const tx = clientX - _clientX;
                        const ty = (0, f_1.clamp)(_dy, 0, exports.TRANSCEND_PULL_DY);
                        const dx = tx - this._x;
                        const dy = ty - this._y;
                        this._translate(tx, ty);
                        if (Math.abs(dx) > 0.1 || dy < 0) {
                            this._pull_tick_count = 0;
                        }
                        if (dy < 0) {
                            this._cancel_pull_tick_frame();
                        }
                        if (ty >= exports.TRANSCEND_PULL_DY) {
                            this._start_pull_timer();
                        }
                    }),
                    (0, pointerup_1.makePointerUpListener)(() => {
                        container.releasePointerCapture(pointerId);
                        this._translate(this._x, 0);
                        this._cancel_pull_tick_frame();
                        this._pointer_down_id = undefined;
                        unlisten();
                    }),
                    (0, pointerleave_1.makePointerLeaveListener)(() => {
                        container.releasePointerCapture(pointerId);
                        this._cancel_pull_tick_frame();
                        this._pointer_down_id = undefined;
                        this._translate(this._x, 0);
                        unlisten();
                    }),
                ]);
            }),
        ]);
        const reset_dim = () => {
            let on_active = () => {
                (0, mergeStyle_1.mergePropStyle)(container, {
                    opacity: '1',
                });
            };
            let on_inactive = () => {
                if (!this._down) {
                    return;
                }
                (0, mergeStyle_1.mergePropStyle)(container, {
                    opacity: `${whenInteracted_1.DIM_OPACITY}`,
                });
            };
            const unlisten_interacted = (0, whenInteracted_1.whenInteracted)(container, 3000, true, on_active, on_inactive);
            on_active();
        };
        reset_dim();
        this._container = container;
        const $element = (0, parentElement_1.parentElement)($system);
        this.$element = $element;
        this.$slot = container.$slot;
        this.$unbundled = false;
        this.$primitive = true;
        this.setSubComponents({
            container,
            icon,
        });
        this.registerRoot(container);
        this._refresh_style();
    }
    onPropChanged(prop, current) {
        if (prop === 'style') {
            this._refresh_style();
        }
    }
    onMount() {
        // console.log('Transcend', 'onMount')
        const {} = this.$context;
        this._translate(this._x, this._y);
        this._context_unlisten = (0, addListener_1.addListeners)(this.$context, [
            (0, resize_1.makeResizeListener)(this._on_context_resize),
        ]);
    }
    onUnmount() {
        // console.log('Transcend', 'onUnmount')
        this._context_unlisten();
    }
    up(animate = true) {
        // console.log('Transcend', 'up')
        if (!this._down) {
            return;
        }
        this._down = false;
        (0, mergeStyle_1.mergePropStyle)(this._icon, {
            transform: `rotate3d(1, 0, 0, 0deg)`,
            transition: animate ? `transform ${ANIMATION_T_S_1.ANIMATION_T_S}s linear` : '',
        });
    }
    down(animate = true) {
        // console.log('Transcend', 'down')
        if (this._down) {
            return;
        }
        this._down = true;
        (0, mergeStyle_1.mergePropStyle)(this._icon, {
            transform: `rotate3d(1, 0, 0, 180deg)`,
            transition: animate ? `transform ${ANIMATION_T_S_1.ANIMATION_T_S}s linear` : '',
        });
    }
    hide(animate = true) {
        // console.log('Transcend', 'hide', animate)
        this._hidden = true;
        if (animate) {
            this._animate_y(-exports.TRANSCEND_HEIGHT);
        }
        else {
            this._y = -exports.TRANSCEND_HEIGHT;
            (0, mergeStyle_1.mergePropStyle)(this._container, {
                top: `${this._y}px`,
            });
        }
    }
    show(animate = true) {
        // console.log('Transcend', 'show', animate)
        this._hidden = false;
        if (animate) {
            this._animate_y(0);
        }
        else {
            this._y = 0;
            (0, mergeStyle_1.mergePropStyle)(this._container, {
                top: `${this._y}px`,
            });
        }
    }
}
exports.default = Transcend;
//# sourceMappingURL=Component.js.map