// #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 { Emit } from '../../../../Events/Decorators/EmitDecorator';
import { Listen } from '../../../../Events/Decorators/ListenDecorator';
import { PanController } from '../../../Controllers/PanController';
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { State } from '../../../Decorators/StateDecorator';
import { PanState } from '../../../Types/PanState';
import { CustomElement } from '../../Abstracts/CustomElement';
import { swipeElementTemplate } from './SwipeElementTemplate';
import { swipeElementJoyStyle } from './Themes/SwipeElement.Joy';
import { swipeElementRetroStyle } from './Themes/SwipeElement.Retro';
import { swipeElementCosmopolitanStyle } from './Themes/SwipeElement.Cosmopolitan';
import { Themeable } from '../../../Behaviors/Themeable';
// #endregion
/**
 * Swipe - A gesture-based interaction for move content by swiping.
 *
 * @description
 * The Swipe component enables users to navigate through content by swiping left or right on a touch-enabled device or using mouse gestures. It is commonly used in carousel sliders, image galleries, and other interfaces where sequential or paginated navigation is required. Swiping gestures allow for intuitive and fluid interaction, enhancing the user experience.
 *
 * @category Primitives
 *
 * @element mosaik-swipe
 *
 * @slot before - The before swipe slot.
 * @slot after - The after swipe slot.
 * @slot - The default content slot.
 *
 * @example
 * ```html
 * <mosaik-swipe>
 *   <!-- content to be swiped -->
 * </mosaik-swipe>
 * ```
 *
 * @public
 */
let SwipeElement = class SwipeElement extends Themeable(CustomElement) {
    // #region Fields
    _beforePanningContainerElement;
    _afterPanningContainerElement;
    _contentContainerElement;
    _panController;
    _panEndTriggeringThreshold;
    _panLeftDisabled;
    _panRightDisabled;
    _leftPanned;
    _rightPanned;
    _panOffset;
    _panState;
    // #endregion
    // #region Ctor
    /**
     * @public
     */
    constructor() {
        super();
        this._panEndTriggeringThreshold = 0.5;
        this._panLeftDisabled = true;
        this._panRightDisabled = true;
        this._panOffset = 0;
        this._panState = PanState.None;
        this._panController = new PanController(this);
    }
    // #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-swipe';
    }
    /**
     * Gets or sets the `panEndTriggeringThreshold` property.
     *
     * @public
     * @attr
     */
    get panEndTriggeringThreshold() {
        return this._panEndTriggeringThreshold;
    }
    set panEndTriggeringThreshold(value) {
        if (this._panEndTriggeringThreshold !== value) {
            this._panEndTriggeringThreshold = value;
            this.requestUpdate('panEndTriggeringThreshold');
        }
    }
    /**
     * Gets or sets the `panLeftDisabled` property.
     *
     * @public
     * @attr
     */
    get panLeftDisabled() {
        return this._panLeftDisabled;
    }
    set panLeftDisabled(value) {
        if (this._panLeftDisabled !== value) {
            this._panLeftDisabled = value;
            this.requestUpdate('panLeftDisabled');
        }
    }
    /**
     * Gets or sets the `panRightDisabled` property.
     *
     * @public
     * @attr
     */
    get panRightDisabled() {
        return this._panRightDisabled;
    }
    set panRightDisabled(value) {
        if (this._panRightDisabled !== value) {
            this._panRightDisabled = value;
            this.requestUpdate('panRightDisabled');
        }
    }
    /**
     * Called when the left swipe gesture is detected.
     * Provides reference to `{@link ISwipeLeftPannedEventDetail}` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get leftPanned() {
        return this._leftPanned;
    }
    /**
     * Called when the right swipe gesture is detected.
     * Provides reference to `{@link ISwipeRightPannedEventDetail}` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get rightPanned() {
        return this._rightPanned;
    }
    // #endregion
    // #region Methods
    /**
     * @public
     */
    panLeft() {
        const minOffset = 48;
        this._panOffset = -this.offsetWidth + minOffset;
        this.setContentElementTransform(this._panOffset);
        this._panState = PanState.Left;
    }
    /**
     * @public
     */
    panRight() {
        const minOffset = 48;
        this._panOffset = this.offsetWidth - minOffset;
        this.setContentElementTransform(this._panOffset);
        this._panState = PanState.Right;
    }
    onApplyTemplate() {
        super.onApplyTemplate();
        this._afterPanningContainerElement = this.getTemplatePart('after-panning');
        this._beforePanningContainerElement = this.getTemplatePart('before-panning');
        this._contentContainerElement = this.getTemplatePart('content-container');
    }
    /**
     * @protected
     */
    onPanStart(_event) {
        if (!this._panLeftDisabled && !this._panRightDisabled) {
        }
    }
    /**
     * @protected
     */
    onPanMove(event) {
        if (!this._panLeftDisabled && !this._panRightDisabled) {
            return;
        }
        const isPanningToLeft = event.detail.deltaX < 0;
        const maxLeft = -this.offsetWidth;
        const maxRight = this.offsetWidth;
        if (isPanningToLeft && this._panLeftDisabled) {
            this._afterPanningContainerElement.hidden = false;
            this._beforePanningContainerElement.hidden = true;
            this.setContentElementTransform(Math.max(maxLeft, event.detail.deltaX));
        }
        else if (!isPanningToLeft && this._panRightDisabled) {
            this._afterPanningContainerElement.hidden = true;
            this._beforePanningContainerElement.hidden = false;
            this.setContentElementTransform(Math.min(maxRight, event.detail.deltaX));
        }
    }
    /**
     * @protected
     */
    onPanEnd(_event) {
        if (!this._panLeftDisabled && !this._panRightDisabled) {
            return;
        }
        // the translation offset of the current list item content
        const relativeOffset = this._panOffset;
        const widthTriggeringGrip = this.offsetWidth * this._panEndTriggeringThreshold;
        if (relativeOffset === 0) {
            return; // no panning has occurred
        }
        const oldPanState = this._panState;
        if (Math.abs(relativeOffset) < widthTriggeringGrip) {
            this.setContentElementTransform(0);
            this._panState = PanState.None;
            this._afterPanningContainerElement.hidden = true;
            this._beforePanningContainerElement.hidden = true;
            return;
        }
        const state = relativeOffset > 0 ? PanState.Right : PanState.Left;
        const maxLeft = -this.offsetWidth;
        const maxRight = this.offsetWidth;
        const args = {
            state: state,
            cancel: false
        };
        if (state === PanState.Left) {
            this._leftPanned.emit(args);
        }
        else {
            this._rightPanned.emit(args);
        }
        if (args.cancel) {
            this.setContentElementTransform(0);
            this._panState = PanState.None;
        }
        else if (state === PanState.Left) {
            this.setContentElementTransform(maxLeft);
            this._panState = PanState.Left;
        }
        else {
            this.setContentElementTransform(maxRight);
            this._panState = PanState.Right;
        }
        if (oldPanState !== this._panState) {
            // this.panStateChange.emit({ sender: this, oldValue: oldPanState, newValue: this._panState });
        }
        this._afterPanningContainerElement.hidden = true;
        this._beforePanningContainerElement.hidden = true;
    }
    /**
     * @private
     */
    setContentElementTransform(value) {
        this._contentContainerElement.style.transform = `translateX(${this._panOffset = value}px)`;
    }
};
__decorate([
    Emit({ eventName: 'leftPanned' }),
    __metadata("design:type", Object)
], SwipeElement.prototype, "_leftPanned", void 0);
__decorate([
    Emit({ eventName: 'rightPanned' }),
    __metadata("design:type", Object)
], SwipeElement.prototype, "_rightPanned", void 0);
__decorate([
    State(),
    __metadata("design:type", Number)
], SwipeElement.prototype, "_panOffset", void 0);
__decorate([
    State(),
    __metadata("design:type", String)
], SwipeElement.prototype, "_panState", void 0);
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], SwipeElement.prototype, "panEndTriggeringThreshold", null);
__decorate([
    Attribute({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], SwipeElement.prototype, "panLeftDisabled", null);
__decorate([
    Attribute({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], SwipeElement.prototype, "panRightDisabled", null);
__decorate([
    Listen('panstart'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Event]),
    __metadata("design:returntype", void 0)
], SwipeElement.prototype, "onPanStart", null);
__decorate([
    Listen('panmove'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CustomEvent]),
    __metadata("design:returntype", void 0)
], SwipeElement.prototype, "onPanMove", null);
__decorate([
    Listen('panend'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Event]),
    __metadata("design:returntype", void 0)
], SwipeElement.prototype, "onPanEnd", null);
SwipeElement = __decorate([
    Component({
        selector: 'mosaik-swipe',
        template: swipeElementTemplate,
        themes: {
            joy: swipeElementJoyStyle,
            retro: swipeElementRetroStyle,
            cosmopolitan: swipeElementCosmopolitanStyle
        },
        imports: []
    }),
    __metadata("design:paramtypes", [])
], SwipeElement);
export { SwipeElement };
//# sourceMappingURL=SwipeElement.js.map