// #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);
};
var SegmentElement_1;
import { Listen } from '../../../../Events/Decorators/ListenDecorator';
import { Appearanceable } from '../../../Behaviors/Appearanceable';
import { Disableable } from '../../../Behaviors/Disableable';
import { Slottable } from '../../../Behaviors/Slottable';
import { Variantable } from '../../../Behaviors/Variantable';
import { KeyboardController } from '../../../Controllers/KeyboardController';
import { ResizeController } from '../../../Controllers/ResizeController';
import { Component } from '../../../Decorators/ComponentDecorator';
import { Watch } from '../../../Decorators/WatchDecorator';
import { FlowDirection } from '../../../Types/FlowDirection';
import { Key } from '../../../Types/Key';
import { Variant } from '../../../Types/Variant';
import { CustomElement } from '../../Abstracts/CustomElement';
import { InkBarElement } from '../../Primitives/InkBar/InkBarElement';
import { segmentElementTemplate } from './SegmentElementTemplate';
import { SegmentItemElement } from './SegmentItemElement';
import { segmentElementJoyStyle } from './Themes/SegmentElement.Joy';
import { segmentElementRetroStyle } from './Themes/SegmentElement.Retro';
import { segmentElementCosmopolitanStyle } from './Themes/SegmentElement.Cosmopolitan';
import { Themeable } from '../../../Behaviors/Themeable';
// #endregion
/**
 * Segment - A group of related buttons arranged in a horizontal row, often used for toggling between different views.
 *
 * @element mosaik-segment
 *
 * @description
 * Segments display a group of related buttons, also known as segmented controls, in a horizontal row. They are designed
 * for toggling between different views or options within the content area. When one segment is selected, others are
 * automatically deselected, similar to radio buttons.
 *
 * Segments are suitable for scenarios where switching between different views within the content area is needed without
 * navigating to a new page. They are commonly used inside toolbars or as part of the main content interface.
 *
 * @category Selectors
 *
 * @keyhandle RightArrow - Selects the next segment.
 * @keyhandle LeftArrow - Selects the previous segment.
 * @keyhandle Home - Selects the first segment.
 * @keyhandle End - Selects the last segment.
 * @keyhandle Enter - Selects the current segment.
 *
 * @example
 * ```html
 * <mosaik-segment>
 *   <mosaik-segment-item>Option 1</mosaik-segment-item>
 *   <mosaik-segment-item>Option 2</mosaik-segment-item>
 *   <mosaik-segment-item>Option 3</mosaik-segment-item>
 * </mosaik-segment>
 * ```
 *
 * @public
 */
let SegmentElement = SegmentElement_1 = class SegmentElement extends Themeable(Slottable(Disableable(Variantable(Appearanceable(CustomElement))))) {
    // #region Fields
    _indicatorElement;
    _resizeController;
    _keyboardController;
    // #endregion
    // #region Ctor
    /**
     * @public
     */
    constructor() {
        super();
        this._indicatorElement = null;
        this._keyboardController = new KeyboardController(this, { capture: true });
        this._resizeController = new ResizeController(this, {
            callback: () => {
                const current = this.getCurrent();
                if (current) {
                    this.alignIndicatorTo(current);
                }
            }
        });
    }
    // #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-segment';
    }
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    connectedCallback() {
        super.connectedCallback();
        this._keyboardController
            .add(Key.RightArrow, () => {
            const current = this.dir === FlowDirection.RightToLeft
                ? this.getItem('previous')
                : this.getItem('next');
            current?.check();
        }, (e) => this.getEnabledItems().includes(e?.target), { preventDefault: true })
            .add(Key.LeftArrow, () => {
            const current = this.dir === FlowDirection.RightToLeft
                ? this.getItem('next')
                : this.getItem('previous');
            current?.check();
        }, (e) => this.getEnabledItems().includes(e?.target), { preventDefault: true })
            .add(Key.Home, (e) => {
            const current = this.getItem('first');
            current?.check();
        }, (e) => this.getEnabledItems().includes(e?.target), { preventDefault: true })
            .add(Key.End, (e) => {
            const current = this.getItem('last');
            current?.check();
        }, (e) => this.getEnabledItems().includes(e?.target), { preventDefault: true })
            .add(Key.Enter, (e) => {
            const current = document.activeElement;
            current.check();
        }, (e) => this.getEnabledItems().includes(e?.target), { preventDefault: true });
    }
    /**
     * @public
     * @override
     */
    onSlotChanges(slotName) {
        super.onSlotChanges(slotName);
        const elements = this.getItems();
        for (const [i, e] of elements.entries()) {
            e.disabled = this.disabled;
            e.variant = this.variant;
            e.dir = this.dir;
            e.classList.toggle('first', i === 0);
            e.classList.toggle('inner', i > 0 && i < elements.length - 1);
            e.classList.toggle('last', i === elements.length - 1);
            if (e.isChecked) {
                this.alignIndicatorTo(e);
            }
        }
    }
    /**
     * @protected
     * @override
     */
    onApplyTemplate() {
        super.onApplyTemplate();
        this._indicatorElement = this.getTemplatePart('indicator');
    }
    /**
     * @protected
     */
    onClick(event) {
        if (event.target instanceof SegmentElement_1) {
            return;
        }
        const current = event.target;
        const previous = this.getCurrent();
        const others = this.getItems()
            .filter((x) => x !== current && x !== previous)
            .filter((x) => !x.isChecked);
        // this.value = current.value;
        if (previous && current !== previous) {
            previous.isChecked = false;
            others.forEach((x) => x.isChecked = false);
            current.isChecked = true;
            // this.checkButton(previous, current);
            this.alignIndicatorTo(current);
        }
        // if (this.scrollable || !this.swipeGesture) {
        //     if (previous) {
        //         this.checkButton(previous, current);
        //     } else {
        //         this.setCheckedClasses();
        //     }
        // }
    }
    /**
     * @protected
     */
    onChecked(event) {
        const current = event.target;
        // const others = this.getSlotAssigmments('')
        //     .filter((x): x is SegmentItemElement => x instanceof SegmentItemElement)
        //     .filter(x => x !== current)
        //     .find((x) => !x.isChecked);
        this.alignIndicatorTo(current);
    }
    onResize(event) {
        const current = this.getCurrent();
        if (current) {
            this.alignIndicatorTo(current);
        }
    }
    /**
     * @protected
     */
    onDisabledPropertyChange(prev, next) {
        if (next !== undefined) {
            this.getItems().forEach((x) => x.disabled = next);
        }
    }
    /**
     * @protected
     */
    onVariantPropertyChange(prev, next) {
        if (next) {
            this.getItems().forEach((x) => x.variant = next);
        }
    }
    /**
     * @protected
     */
    onDirPropertyChange(prev, next) {
        if (next) {
            this.getItems().forEach((x) => x.dir = next);
        }
    }
    /**
     * @private
     */
    alignIndicatorTo(element) {
        if (this._indicatorElement) {
            this._indicatorElement.target = element;
            this._indicatorElement.align();
        }
    }
    /**
     * @private
     */
    getItems() {
        return this.getSlotAssignmentsOf('', SegmentItemElement);
    }
    /**
     * @private
     */
    getEnabledItems() {
        return this.getItems().filter((x) => !x.disabled);
    }
    /**
     * @private
     */
    getCurrent() {
        return this.getItems().find((x) => x.isChecked) ?? null;
    }
    /**
     * @private
     */
    getItem(selector) {
        const items = this.getItems().filter((item) => !item.disabled);
        const currIndex = items.findIndex((item) => item === document.activeElement);
        switch (selector) {
            case 'first':
                return items[0];
            case 'last':
                return items[items.length - 1];
            case 'next':
                return items[currIndex + 1] ?? items[0];
            case 'previous':
                return items[currIndex - 1] ?? items[items.length - 1];
            default:
                return null;
        }
    }
};
__decorate([
    Listen('click'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Event]),
    __metadata("design:returntype", void 0)
], SegmentElement.prototype, "onClick", null);
__decorate([
    Listen('checked'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CustomEvent]),
    __metadata("design:returntype", void 0)
], SegmentElement.prototype, "onChecked", null);
__decorate([
    Listen('resize', 'window'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CustomEvent]),
    __metadata("design:returntype", void 0)
], SegmentElement.prototype, "onResize", null);
__decorate([
    Watch('disabled'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Boolean, Boolean]),
    __metadata("design:returntype", void 0)
], SegmentElement.prototype, "onDisabledPropertyChange", null);
__decorate([
    Watch('variant'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", void 0)
], SegmentElement.prototype, "onVariantPropertyChange", null);
__decorate([
    Watch('dir'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", void 0)
], SegmentElement.prototype, "onDirPropertyChange", null);
SegmentElement = SegmentElement_1 = __decorate([
    Component({
        selector: 'mosaik-segment',
        template: segmentElementTemplate,
        themes: {
            joy: segmentElementJoyStyle,
            retro: segmentElementRetroStyle,
            cosmopolitan: segmentElementCosmopolitanStyle
        },
        imports: [
            InkBarElement
        ]
    }),
    __metadata("design:paramtypes", [])
], SegmentElement);
export { SegmentElement };
//# sourceMappingURL=SegmentElement.js.map