// #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 { HTMLElementEventEmitter, on } from '@breadstone/mosaik-elements';
import { Emit } from '../../../../events/Decorators/EmitDecorator';
import { Attachable } from '../../../Behaviors/Attachable';
import { Disableable } from '../../../Behaviors/Disableable';
import { Themeable } from '../../../Behaviors/Themeable';
import { ResizeThumbController } from '../../../Controllers/ResizeThumbController';
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { ALL_RESIZE_DIRECTIONS, ResizeDirection } from '../../../Types/ResizeDirection';
import { CustomElement } from '../../Abstracts/CustomElement';
import { resizeThumbElementTemplate } from './ResizeThumbElementTemplate';
import { resizeThumbElementCosmopolitanStyle } from './Themes/ResizeThumbElement.Cosmopolitan';
import { resizeThumbElementJoyStyle } from './Themes/ResizeThumbElement.Joy';
import { resizeThumbElementMemphisStyle } from './Themes/ResizeThumbElement.Memphis';
// #endregion
/**
 * ResizeThumb - A primitive element that provides resize handle functionality.
 *
 * @description
 * The ResizeThumb element is a low-level primitive that signals resizing capability
 * in a specific direction. It handles user interactions (mouse/touch) and automatically
 * resizes the attached control element.
 *
 * The element uses the Attachable behavior to connect to its target element, either
 * through the `for` attribute referencing an element ID, or by automatically attaching
 * to its parent element.
 *
 * Internally, this element uses a `ResizeThumbController` for all resize logic.
 * For programmatic usage without a visual thumb, use the controller directly.
 *
 * This element has minimal visual appearance by design - parent components like Dialog,
 * Sheet, or Panel are expected to style the thumb appropriately for their context.
 *
 * @name ResizeThumb
 * @element mosaik-resize-thumb
 * @category Primitive
 *
 * @csspart thumb - The main thumb element.
 *
 * @cssprop {String} --resize-thumb-border-color - The thumb border color CSS custom property.
 * @cssprop {String} --resize-thumb-border-radius - The thumb border radius CSS custom property.
 * @cssprop {String} --resize-thumb-border-style - The thumb border style CSS custom property.
 * @cssprop {String} --resize-thumb-border-width - The thumb border width CSS custom property.
 * @cssprop {String} --resize-thumb-font-family - The thumb font family CSS custom property.
 * @cssprop {String} --resize-thumb-font-letter-spacing - The thumb font letter spacing CSS custom property.
 * @cssprop {String} --resize-thumb-font-line-height - The thumb font line height CSS custom property.
 * @cssprop {String} --resize-thumb-font-size - The thumb font size CSS custom property.
 * @cssprop {String} --resize-thumb-font-text-decoration - The thumb font text decoration CSS custom property.
 * @cssprop {String} --resize-thumb-font-text-transform - The thumb font text transform CSS custom property.
 * @cssprop {String} --resize-thumb-font-weight - The thumb font weight CSS custom property.
 * @cssprop {String} --resize-thumb-gap - The thumb gap CSS custom property.
 * @cssprop {String} --resize-thumb-padding-bottom - The thumb padding bottom CSS custom property.
 * @cssprop {String} --resize-thumb-padding-left - The thumb padding left CSS custom property.
 * @cssprop {String} --resize-thumb-padding-right - The thumb padding right CSS custom property.
 * @cssprop {String} --resize-thumb-padding-top - The thumb padding top CSS custom property.
 * @cssprop {String} --resize-thumb-shadow - The thumb shadow CSS custom property.
 * @cssprop {String} --resize-thumb-shadow-blur - The thumb shadow blur CSS custom property.
 * @cssprop {String} --resize-thumb-shadow-color - The thumb shadow color CSS custom property.
 * @cssprop {String} --resize-thumb-shadow-offset-x - The thumb shadow offset x CSS custom property.
 * @cssprop {String} --resize-thumb-shadow-offset-y - The thumb shadow offset y CSS custom property.
 * @cssprop {String} --resize-thumb-shadow-spread - The thumb shadow spread CSS custom property.
 * @cssprop {String} --resize-thumb-thumb-background-color - The thumb thumb background color CSS custom property.
 * @cssprop {String} --resize-thumb-thumb-border-radius - The thumb thumb border radius CSS custom property.
 * @cssprop {String} --resize-thumb-transition-duration - The thumb transition duration CSS custom property.
 * @cssprop {String} --resize-thumb-transition-mode - The thumb transition mode CSS custom property.
 * @cssprop {String} --resize-thumb-transition-property - The thumb transition property CSS custom property.
 * @cssprop {String} --resize-thumb-translate - The thumb translate CSS custom property.
 *
 * @fires resizeStart {ResizeStartEvent} - Fired when a resize operation begins.
 * @fires resizing {ResizingEvent} - Fired continuously during a resize operation.
 * @fires resizeEnd {ResizeEndEvent} - Fired when a resize operation ends.
 *
 * @dependency mosaik-thumb - The Thumb element.
 *
 * @example
 * ```html
 * <!-- Inside a parent element (attaches to parent) -->
 * <mosaik-dialog>
 *   <mosaik-resize-thumb direction="south-east"></mosaik-resize-thumb>
 * </mosaik-dialog>
 *
 * <!-- Attached to specific element via for attribute -->
 * <div id="resizable-box" style="width: 200px; height: 150px;">
 *   Content
 * </div>
 * <mosaik-resize-thumb for="resizable-box" direction="south-east"></mosaik-resize-thumb>
 *
 * <!-- With constraints -->
 * <mosaik-resize-thumb
 *   direction="south-east"
 *   min-width="100"
 *   min-height="80"
 *   max-width="500"
 *   max-height="400">
 * </mosaik-resize-thumb>
 *
 * <!-- Manual resize handling via events (auto-apply disabled via JavaScript) -->
 * <mosaik-resize-thumb id="manualThumb" direction="east"></mosaik-resize-thumb>
 * <script>
 *   document.querySelector('#manualThumb').autoApply = false;
 * </script>
 * ```
 *
 * @public
 *
 * @see `ResizeThumbController` for programmatic usage without visual element.
 */
let ResizeThumbElement = class ResizeThumbElement extends Themeable(Disableable(Attachable(CustomElement))) {
    // #region Fields
    _resizeStart;
    _resizing;
    _resizeEnd;
    _direction;
    _allowedDirections;
    _minWidth;
    _minHeight;
    _maxWidth;
    _maxHeight;
    _autoApply;
    _controller;
    _mouseDownSubscription;
    _touchStartSubscription;
    // #endregion
    // #region Ctor
    /**
     * @public
     */
    constructor() {
        super();
        this._direction = ResizeDirection.SouthEast;
        this._allowedDirections = ALL_RESIZE_DIRECTIONS;
        this._minWidth = 0;
        this._minHeight = 0;
        this._maxWidth = Number.MAX_SAFE_INTEGER;
        this._maxHeight = Number.MAX_SAFE_INTEGER;
        this._autoApply = true;
        this._controller = null;
        this._mouseDownSubscription = null;
        this._touchStartSubscription = null;
        this._resizeStart = new HTMLElementEventEmitter(this, 'resizeStart');
        this._resizing = new HTMLElementEventEmitter(this, 'resizing');
        this._resizeEnd = new HTMLElementEventEmitter(this, 'resizeEnd');
    }
    // #endregion
    // #region Properties
    /**
     * Returns the `is` property.
     * The `is` property represents natural name of this element.
     *
     * @public
     * @static
     * @readonly
     */
    static get is() {
        return 'mosaik-resize-thumb';
    }
    /**
     * Gets or sets the resize `direction`.
     *
     * Determines which direction this resize thumb represents.
     * The cursor style is automatically updated based on this direction.
     *
     * @attr
     * @public
     */
    get direction() {
        return this._direction;
    }
    set direction(value) {
        if (this._direction !== value) {
            this._direction = value;
            if (this._controller) {
                this._controller.direction = value;
            }
            this.requestUpdate('direction');
        }
    }
    /**
     * Gets or sets the `allowedDirections` array.
     *
     * When set, only the specified directions are permitted for resizing.
     * If the current direction is not in the allowed list, resize operations
     * will be blocked.
     *
     * @attr
     * @public
     */
    get allowedDirections() {
        return this._allowedDirections;
    }
    set allowedDirections(value) {
        if (this._allowedDirections !== value) {
            this._allowedDirections = value;
            this.requestUpdate('allowedDirections');
        }
    }
    /**
     * Gets or sets the minimum width the control can be resized to.
     *
     * @attr min-width
     * @public
     */
    get minWidth() {
        return this._minWidth;
    }
    set minWidth(value) {
        if (this._minWidth !== value) {
            this._minWidth = value;
            if (this._controller) {
                this._controller.minWidth = value;
            }
            this.requestUpdate('minWidth');
        }
    }
    /**
     * Gets or sets the minimum height the control can be resized to.
     *
     * @attr min-height
     * @public
     */
    get minHeight() {
        return this._minHeight;
    }
    set minHeight(value) {
        if (this._minHeight !== value) {
            this._minHeight = value;
            if (this._controller) {
                this._controller.minHeight = value;
            }
            this.requestUpdate('minHeight');
        }
    }
    /**
     * Gets or sets the maximum width the control can be resized to.
     *
     * @attr max-width
     * @public
     */
    get maxWidth() {
        return this._maxWidth;
    }
    set maxWidth(value) {
        if (this._maxWidth !== value) {
            this._maxWidth = value;
            if (this._controller) {
                this._controller.maxWidth = value;
            }
            this.requestUpdate('maxWidth');
        }
    }
    /**
     * Gets or sets the maximum height the control can be resized to.
     *
     * @attr max-height
     * @public
     */
    get maxHeight() {
        return this._maxHeight;
    }
    set maxHeight(value) {
        if (this._maxHeight !== value) {
            this._maxHeight = value;
            if (this._controller) {
                this._controller.maxHeight = value;
            }
            this.requestUpdate('maxHeight');
        }
    }
    /**
     * Gets or sets whether resize changes are automatically applied to the control element.
     * If false, only events are emitted and the control is responsible for applying changes.
     * Defaults to true.
     *
     * @attr auto-apply
     * @public
     */
    get autoApply() {
        return this._autoApply;
    }
    set autoApply(value) {
        if (this._autoApply !== value) {
            this._autoApply = value;
            if (this._controller) {
                this._controller.autoApply = value;
            }
            this.requestUpdate('autoApply');
        }
    }
    /**
     * Gets whether a resize operation is currently in progress.
     *
     * @public
     * @readonly
     */
    get isResizing() {
        return this._controller?.isResizing ?? false;
    }
    /**
     * Called when a resize operation starts.
     * Provides reference to `IResizeStartEventDetail` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get resizeStart() {
        return this._resizeStart;
    }
    /**
     * Called during a resize operation.
     * Provides reference to `IResizingEventDetail` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get resizing() {
        return this._resizing;
    }
    /**
     * Called when a resize operation ends.
     * Provides reference to `IResizeEndEventDetail` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get resizeEnd() {
        return this._resizeEnd;
    }
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    connectedCallback() {
        super.connectedCallback();
        this.initializeController();
    }
    /**
     * @public
     * @override
     */
    disconnectedCallback() {
        this._mouseDownSubscription?.dispose();
        this._touchStartSubscription?.dispose();
        this._controller?.dispose();
        this._controller = null;
        super.disconnectedCallback();
    }
    /**
     * @protected
     * @override
     */
    onApplyTemplate() {
        const thumb = this.getTemplatePart('thumb');
        this._mouseDownSubscription = on(thumb, 'mousedown', (e) => this.onPointerStart(e.clientX, e.clientY, e));
        this._touchStartSubscription = on(thumb, 'touchstart', (e) => {
            if (e.touches.length === 1) {
                this.onPointerStart(e.touches[0].clientX, e.touches[0].clientY, e);
            }
        }, { passive: false });
    }
    /**
     * Checks if the current direction is allowed.
     *
     * @protected
     * @returns True if the direction is in the allowed list, false otherwise.
     */
    isDirectionAllowed() {
        return this._allowedDirections.includes(this._direction);
    }
    /**
     * Handles the start of a pointer (mouse or touch) interaction.
     *
     * @protected
     */
    onPointerStart(clientX, clientY, event) {
        if (this.disabled || !this.isDirectionAllowed() || !this._controller) {
            return;
        }
        event.preventDefault();
        this._controller.startResize(clientX, clientY);
    }
    /**
     * Initializes or re-initializes the controller with the current control element.
     *
     * @private
     */
    initializeController() {
        // Dispose existing controller
        this._controller?.dispose();
        this._controller = null;
        // Wait for control to be available
        if (!this.control) {
            return;
        }
        // Create new controller
        this._controller = new ResizeThumbController({
            target: this.control,
            direction: this._direction,
            minWidth: this._minWidth,
            minHeight: this._minHeight,
            maxWidth: this._maxWidth,
            maxHeight: this._maxHeight,
            autoApply: this._autoApply,
            onResizeStart: (event) => {
                this._resizeStart.emit({
                    direction: event.direction,
                    startX: event.startX,
                    startY: event.startY
                });
            },
            onResizing: (event) => {
                this._resizing.emit({
                    direction: event.direction,
                    deltaX: event.deltaX,
                    deltaY: event.deltaY,
                    currentX: event.currentX,
                    currentY: event.currentY,
                    newWidth: event.newWidth,
                    newHeight: event.newHeight
                });
            },
            onResizeEnd: (event) => {
                this._resizeEnd.emit({
                    direction: event.direction,
                    totalDeltaX: event.totalDeltaX,
                    totalDeltaY: event.totalDeltaY,
                    finalWidth: event.finalWidth,
                    finalHeight: event.finalHeight
                });
            }
        });
    }
};
__decorate([
    Emit({ eventName: 'resizeStart' }),
    __metadata("design:type", Object)
], ResizeThumbElement.prototype, "_resizeStart", void 0);
__decorate([
    Emit({ eventName: 'resizing' }),
    __metadata("design:type", Object)
], ResizeThumbElement.prototype, "_resizing", void 0);
__decorate([
    Emit({ eventName: 'resizeEnd' }),
    __metadata("design:type", Object)
], ResizeThumbElement.prototype, "_resizeEnd", void 0);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ResizeThumbElement.prototype, "direction", null);
__decorate([
    Attribute({
        type: Array,
        converter: {
            fromAttribute: (value) => value.split(' ').map((p) => p.trim())
                .filter((p) => p !== ''),
            toAttribute: (value) => value.join(' ')
        }
    }),
    __metadata("design:type", Array),
    __metadata("design:paramtypes", [Array])
], ResizeThumbElement.prototype, "allowedDirections", null);
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], ResizeThumbElement.prototype, "minWidth", null);
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], ResizeThumbElement.prototype, "minHeight", null);
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], ResizeThumbElement.prototype, "maxWidth", null);
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], ResizeThumbElement.prototype, "maxHeight", null);
__decorate([
    Attribute({
        type: Boolean
        // useDefault: true -  TODO: use a false based name
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ResizeThumbElement.prototype, "autoApply", null);
ResizeThumbElement = __decorate([
    Component({
        selector: 'mosaik-resize-thumb',
        template: resizeThumbElementTemplate,
        themes: {
            joy: resizeThumbElementJoyStyle,
            memphis: resizeThumbElementMemphisStyle,
            cosmopolitan: resizeThumbElementCosmopolitanStyle
        },
        imports: []
    }),
    __metadata("design:paramtypes", [])
], ResizeThumbElement);
export { ResizeThumbElement };
//# sourceMappingURL=ResizeThumbElement.js.map