// #region Imports
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { RendererServiceLocator } from '../../../../Dom/Renderer';
import { on } from '@breadstone/mosaik-elements';
import { CssLength } from '@breadstone/mosaik-themes';
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { Property } from '../../../Decorators/PropertyDecorator';
import { IconElement } from '../../Media/Icon/IconElement';
import { BackdropElement } from '../../Primitives/Backdrop/BackdropElement';
import { TextElement } from '../../Primitives/Text/TextElement';
import { OverlayElement } from '../Abstracts/OverlayElement';
import { sheetElementTemplate } from './SheetElementTemplate';
import { sheetElementJoyStyle } from './Themes/SheetElement.Joy';
import { sheetElementMemphisStyle } from './Themes/SheetElement.Memphis';
import { sheetElementCosmopolitanStyle } from './Themes/SheetElement.Cosmopolitan';
import { Themeable } from '../../../Behaviors/Themeable';
/**
 * The `{@link SheetElement}` element.
 *
 * @public
 */
let SheetElement = class SheetElement extends Themeable(OverlayElement) {
    // #region Fields
    _bounceOffset;
    _header;
    _content;
    _icon;
    _height;
    _dragOffset;
    _positionY;
    _isPartial;
    _mouseDownSubscription;
    _touchStartSubscription;
    _mouseUpSubscription;
    _touchEndSubscription;
    _mouseMoveSubscription;
    _touchMoveSubscription;
    _clickSubscription;
    // #endregion
    // #region Ctor
    /**
     * @public
     */
    constructor() {
        super();
        this._header = '';
        this._content = '';
        this._icon = '';
        this._height = '60vh';
        this._dragOffset = 0;
        this._bounceOffset = 35;
        this._positionY = 0;
        this._isPartial = false;
        this._mouseDownSubscription = null;
        this._touchStartSubscription = null;
        this._mouseUpSubscription = null;
        this._touchEndSubscription = null;
        this._mouseMoveSubscription = null;
        this._touchMoveSubscription = null;
        this._clickSubscription = null;
    }
    // #endregion
    // #region Properties
    /**
     * Returns the `{@link is}` property.
     * The `{@link is}` property represents natural name of this element.
     *
     * @public
     * @static
     * @readonly
     */
    static get is() {
        return 'mosaik-sheet';
    }
    /**
     * Gets or sets the `header` property.
     *
     * @public
     */
    get header() { return this._header; }
    set header(value) {
        if (this._header !== value) {
            this._header = value;
            this.requestUpdate('header');
        }
    }
    /**
     * Gets or sets the `content` property.
     *
     * @public
     */
    get content() { return this._content; }
    set content(value) {
        if (this._content !== value) {
            this._content = value;
            this.requestUpdate('content');
        }
    }
    /**
     * Gets or sets the `icon` property.
     *
     * @public
     */
    get icon() { return this._icon; }
    set icon(value) {
        if (this._icon !== value) {
            this._icon = value;
            this.requestUpdate('icon');
        }
    }
    /**
     * Gets or sets the `height` property.
     *
     * @public
     * @attr
     */
    get height() {
        return this._height;
    }
    set height(value) {
        if (this._height !== value) {
            this._height = value;
            this.requestUpdate('height');
        }
    }
    // #endregion
    // #region Methods
    /**
     * Opens the `SheetElement`.
     *
     * @public
     * @override
     */
    async open() {
        return super.open().then(() => {
            const root = this.getTemplatePart('root');
            this.moveDragElement(window.innerHeight - root.clientHeight, 'open');
            RendererServiceLocator.current.setAttribute(this, 'state', 'open');
        });
    }
    /**
     * Closes the `SheetElement`.
     *
     * @public
     * @override
     */
    async close() {
        return super.close().then((x) => {
            if (x) {
                if (this.closeable) {
                    this.moveDragElement(window.innerHeight + 50, 'close');
                    RendererServiceLocator.current.setAttribute(this, 'state', 'close');
                }
            }
            return x;
        });
    }
    /**
     * @public
     */
    partial() {
        const heading = this.getTemplatePart('heading');
        this.moveDragElement(window.innerHeight - heading.clientHeight - this._bounceOffset, 'partial');
        RendererServiceLocator.current.setAttribute(this, 'state', 'partial');
    }
    /**
     * @public
     */
    async toggle() {
        if (this._isPartial) {
            return this.open();
        }
        this.partial();
        return Promise.resolve();
    }
    /**
     * @protected
     * @override
     */
    onApplyTemplate() {
        super.onApplyTemplate();
        const heading = this.getTemplatePart('heading');
        this._clickSubscription = on(heading, 'click', () => void this.toggle());
        this._mouseDownSubscription = on(heading, 'mousedown', (e) => this.dragMouseDown(e));
        this._touchStartSubscription = on(heading, 'touchstart', (e) => this.dragMouseDown(e), { passive: true });
    }
    /**
     * Handles the backdrop click event.
     * Only closes the sheet if `clickOutsideToClose` is enabled.
     *
     * @private
     * @template
     */
    onBackdrop() {
        if (this.clickOutsideToClose) {
            void this.close();
        }
    }
    /**
     * @private
     */
    dragMouseDown(e) {
        const target = e.target;
        this._mouseUpSubscription = on(window, 'mouseup', (x) => this.dragMouseUp(x));
        this._mouseMoveSubscription = on(window, 'mousemove', (x) => this.dragMouseMove(x));
        this._touchEndSubscription = on(window, 'touchend', (x) => this.dragMouseUp(x));
        this._touchMoveSubscription = on(window, 'touchmove', (x) => this.dragMouseMove(x));
        this._positionY = this.getYCoord(e);
        this._dragOffset = this._positionY - target.getBoundingClientRect().top;
        document.body.style.overscrollBehaviorY = 'none';
    }
    /**
     * @private
     */
    dragMouseUp(e) {
        const root = this.getTemplatePart('root');
        const heading = this.getTemplatePart('heading');
        //  document.body.style.overscrollBehaviorY = this._saveBodyStyle;
        this._positionY = this.getYCoord(e);
        if (this.closeable && this._positionY >= window.innerHeight - 25) {
            // snap to close position.
            this.moveDragElement(window.innerHeight + 50, 'close');
            RendererServiceLocator.current.setAttribute(this, 'state', 'close');
            this._isPartial = false;
            return;
        }
        if (window.innerHeight - this._positionY > root.clientHeight / 2.5) {
            // snap to open position.
            this.moveDragElement(window.innerHeight - root.clientHeight, 'open');
            RendererServiceLocator.current.setAttribute(this, 'state', 'open');
            this._isPartial = false;
        }
        else {
            // snap to initial position.
            // only when the header is visible.
            this.moveDragElement(window.innerHeight - heading.clientHeight - this._bounceOffset, 'partial');
            RendererServiceLocator.current.setAttribute(this, 'state', 'partial');
            this._isPartial = true;
        }
    }
    /**
     * @private
     */
    dragMouseMove(e) {
        const root = this.getTemplatePart('root');
        this._positionY = this.getYCoord(e);
        if (this._positionY <= (window.innerHeight - root.clientHeight + this._dragOffset)) {
            return;
        }
        root.style.setProperty('transition', 'none');
        root.style.setProperty('--translateY', `translateY(${this._positionY - this._dragOffset}px)`);
    }
    /**
     * @private
     */
    moveDragElement(toPoint, state) {
        const root = this.getTemplatePart('root');
        const heading = this.getTemplatePart('heading');
        this._mouseUpSubscription?.dispose();
        this._touchEndSubscription?.dispose();
        this._mouseMoveSubscription?.dispose();
        this._touchMoveSubscription?.dispose();
        if (!toPoint && this._positionY >= window.innerHeight - heading.clientHeight) {
            root.style.setProperty('--translateY', `translateY(calc(100vh - ${heading.clientHeight}px))`);
        }
        else {
            root.style.setProperty('--translateY', `translateY(${(toPoint || this._positionY) + this._bounceOffset}px)`);
        }
        root.style.setProperty('transition', 'transform 500ms cubic-bezier(0.4, 0, 0, 1) 0s');
        if (state === 'close') {
            this._mouseDownSubscription?.dispose();
            this._touchStartSubscription?.dispose();
            this._clickSubscription?.dispose();
            setTimeout(() => {
                this._mouseDownSubscription?.dispose();
                this._touchStartSubscription?.dispose();
            }, 250);
        }
    }
    /**
     * @private
     */
    getYCoord(e) {
        let y = 0;
        let x = 0;
        if (e instanceof MouseEvent) {
            y = e.clientY;
            x = e.clientX;
        }
        else if (e instanceof PointerEvent) {
            y = e.changedTouches[0].clientY;
            x = e.changedTouches[0].clientX;
        }
        return y;
    }
};
__decorate([
    Property({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], SheetElement.prototype, "header", null);
__decorate([
    Property({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], SheetElement.prototype, "content", null);
__decorate([
    Property({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], SheetElement.prototype, "icon", null);
__decorate([
    Attribute({ type: CssLength }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [Object])
], SheetElement.prototype, "height", null);
SheetElement = __decorate([
    Component({
        selector: 'mosaik-sheet',
        template: sheetElementTemplate,
        themes: {
            joy: sheetElementJoyStyle,
            memphis: sheetElementMemphisStyle,
            cosmopolitan: sheetElementCosmopolitanStyle
        },
        imports: [
            TextElement,
            IconElement,
            BackdropElement
        ]
    }),
    __metadata("design:paramtypes", [])
], SheetElement);
export { SheetElement };
//# sourceMappingURL=SheetElement.js.map