// #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 FlowBoardColumnElement_1;
import { HTMLElementEventEmitter } from '@breadstone/mosaik-elements';
import { DragController, DropListController } from '../../../../DragDrop';
import { EID } from '../../../../Utilities/EId';
import { Slottable } from '../../../Behaviors/Slottable';
import { Themeable } from '../../../Behaviors/Themeable';
import { addInheritanceConsumerController } from '../../../Controllers/InheritanceConsumerController';
import { addInheritanceProviderController } from '../../../Controllers/InheritanceProviderController';
import { addSlotController } from '../../../Controllers/SlotController';
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { Watch } from '../../../Decorators/WatchDecorator';
import { CustomElement } from '../../Abstracts/CustomElement';
import { flowBoardColumnElementTemplate } from './FlowBoardColumnElementTemplate';
import { FLOW_BOARD_COLUMN_INHERITANCE_CONTEXT } from './FlowBoardColumnInheritanceContext';
import { FlowBoardColumnItemComposerElement } from './FlowBoardColumnItemComposerElement';
import { FlowBoardColumnItemElement } from './FlowBoardColumnItemElement';
import { FLOW_BOARD_INHERITANCE_CONTEXT } from './FlowBoardInheritanceContext';
import { IFlowBoardColumnElementProps } from './IFlowBoardColumnElementProps';
import { flowBoardColumnElementCosmopolitanStyle } from './Themes/FlowBoardColumnElement.Cosmopolitan';
import { flowBoardColumnElementJoyStyle } from './Themes/FlowBoardColumnElement.Joy';
import { flowBoardColumnElementMemphisStyle } from './Themes/FlowBoardColumnElement.Memphis';
// #endregion
/**
 * FlowBoardColumn - A column in a FlowBoard.
 *
 * Represents a single column in a FlowBoard, containing items and optional header/footer.
 * Supports reordering, pinning, and empty state rendering.
 *
 * @name FlowBoardColumnElement
 * @element mosaik-flow-board-column
 * @category Layouts
 *
 * @slot - Default slot for FlowBoardColumnItem elements
 * @slot title - The title content of the column header
 * @slot meta - Metadata content (badges, counts, KPIs)
 * @slot actions - Action buttons for the column
 * @slot footer - Footer content (usually contains a composer)
 * @slot empty - Content to show when the column has no items
 *
 * @csspart container - The main container element
 * @csspart header - The column header section
 * @csspart title - The title wrapper
 * @csspart meta - The meta information wrapper
 * @csspart actions - The actions wrapper
 * @csspart body - The main body containing items
 * @csspart footer - The footer section
 * @csspart empty - The empty state container
 *
 * @cssprop {Color} --flow-board-column-background-color - Background color of the column
 * @cssprop {String} --flow-board-column-border-radius - Border radius of the column
 * @cssprop {String} --flow-board-column-padding - Internal padding
 * @cssprop {String} --flow-board-column-gap - Gap between items
 * @cssprop {String} --flow-board-column-min-width - Minimum width of the column
 * @cssprop {String} --flow-board-column-max-width - Maximum width of the column
 *
 * @fires flowBoardBeforeColumnPinChange {FlowBoardBeforeColumnPinChangeEvent} - Fired before pin state changes
 * @fires flowBoardColumnPinChange {FlowBoardColumnPinChangeEvent} - Fired when pin state changes
 *
 * @dependency FlowBoardColumnItemElement - Item component
 * @dependency FlowBoardColumnItemComposerElement - Composer component
 *
 * @example
 * ```html
 * <mosaik-flow-board-column column-key="todo" reorderable>
 *   <div slot="title">To Do</div>
 *   <mosaik-flow-board-column-item item-key="task-1">
 *     <span slot="title">Task 1</span>
 *   </mosaik-flow-board-column-item>
 *   <mosaik-flow-board-column-item item-key="task-2">
 *     <span slot="title">Task 2</span>
 *   </mosaik-flow-board-column-item>
 *   <mosaik-flow-board-column-item-composer slot="footer"></mosaik-flow-board-column-item-composer>
 * </mosaik-flow-board-column>
 * ```
 *
 * @public
 */
let FlowBoardColumnElement = FlowBoardColumnElement_1 = class FlowBoardColumnElement extends Themeable(Slottable(CustomElement)) {
    // #region Fields
    _columnKey;
    _reorderable;
    _pinned;
    _hasItems;
    _flowBoardBeforeColumnPinChange;
    _flowBoardColumnPinChange;
    _slotController;
    _inheritance;
    _provider;
    _dragCtrl;
    _itemDropList;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `FlowBoardColumnElement` class.
     *
     * @public
     */
    constructor() {
        super();
        this._columnKey = IFlowBoardColumnElementProps.DEFAULTS.columnKey;
        this._reorderable = IFlowBoardColumnElementProps.DEFAULTS.reorderable;
        this._pinned = IFlowBoardColumnElementProps.DEFAULTS.pinned;
        this._hasItems = false;
        this._flowBoardBeforeColumnPinChange = new HTMLElementEventEmitter(this, 'flowBoardBeforeColumnPinChange');
        this._flowBoardColumnPinChange = new HTMLElementEventEmitter(this, 'flowBoardColumnPinChange');
        this._slotController = addSlotController(this, {
            callback: () => this.updateHasItems()
        });
        this._inheritance = addInheritanceConsumerController(this, {
            context: FLOW_BOARD_INHERITANCE_CONTEXT
        });
        this._provider = addInheritanceProviderController(this, {
            context: FLOW_BOARD_COLUMN_INHERITANCE_CONTEXT,
            values: () => ({
                columnKey: this._columnKey
            })
        });
        this._dragCtrl = new DragController(this, {
            disabled: true
        });
        this._itemDropList = new DropListController(this, {
            orientation: 'vertical',
            disabled: true
        });
    }
    // #endregion
    // #region Properties
    /**
     * Returns the `is` property.
     *
     * @public
     * @static
     * @readonly
     */
    static get is() {
        return 'mosaik-flow-board-column';
    }
    /**
     * Gets or sets the unique key for the column.
     * If not provided, a key will be generated on connect.
     *
     * @public
     * @attr column-key
     */
    get columnKey() {
        return this._columnKey;
    }
    set columnKey(value) {
        if (this._columnKey !== value) {
            this._columnKey = value;
            this._provider.update();
            this.requestUpdate('columnKey');
        }
    }
    /**
     * Gets or sets whether the column can be reordered.
     * Column can only be dragged if this is true, board has dragdrop, and column is not pinned.
     *
     * @public
     * @attr
     */
    get reorderable() {
        return this._reorderable;
    }
    set reorderable(value) {
        if (this._reorderable !== value) {
            this._reorderable = value;
            this.requestUpdate('reorderable');
        }
    }
    /**
     * Gets or sets whether the column is pinned (fixed position).
     * Pinned columns cannot be dragged and their index is preserved during reordering.
     *
     * @public
     * @attr
     */
    get pinned() {
        return this._pinned;
    }
    set pinned(value) {
        if (this._pinned !== value) {
            this._pinned = value;
            this.requestUpdate('pinned');
        }
    }
    /**
     * Whether the column has any items in the default slot.
     *
     * @public
     * @readonly
     */
    get hasItems() {
        return this._hasItems;
    }
    /**
     * Whether drag and drop is enabled from the parent board.
     *
     * @public
     * @readonly
     */
    get isDragEnabled() {
        return this._inheritance.get('dragdrop', false);
    }
    /**
     * Whether the column can currently be dragged.
     * Returns true only if reorderable, not pinned, and drag is enabled on the board.
     *
     * @public
     * @readonly
     */
    get canDrag() {
        return this._reorderable && !this._pinned && this.isDragEnabled;
    }
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    connectedCallback() {
        super.connectedCallback();
        // Generate key if not provided
        if (!this._columnKey) {
            this._columnKey = EID.next(FlowBoardColumnElement_1.is);
            this._provider.update();
        }
        // Update drag/drop controller states based on inherited context
        this._dragCtrl.disabled = !this.canDrag;
        this._itemDropList.disabled = !this.isDragEnabled;
        this.updateHasItems();
    }
    /**
     * Gets all item elements in this column.
     *
     * @public
     * @returns Array of FlowBoardColumnItemElement.
     */
    getItems() {
        const slot = this.shadowRoot?.querySelector('slot:not([name])');
        const elements = slot?.assignedElements({ flatten: true }) ?? [];
        return elements.filter((el) => el instanceof FlowBoardColumnItemElement);
    }
    /**
     * Returns this column's DragRef for registration with a parent DropList.
     *
     * @public
     * @returns The DragRef or null.
     */
    getDragRef() {
        return this._dragCtrl.dragRef;
    }
    /**
     * Returns this column's item DropListRef for cross-column connectivity.
     *
     * @public
     * @returns The DropListRef or null.
     */
    getDropListRef() {
        return this._itemDropList.dropListRef;
    }
    /**
     * Discovers item DragRefs and registers them with this column's DropList.
     * Should be called after slot changes when items are added/removed.
     *
     * @public
     */
    syncItemDragRefs() {
        const items = this.getItems();
        const dragRefs = items
            .map((item) => item.getDragRef())
            .filter((ref) => ref !== null);
        this._itemDropList.withItems(dragRefs);
    }
    /**
     * Gets the pinned items in this column.
     *
     * @public
     * @returns Array of pinned FlowBoardColumnItemElement.
     */
    getPinnedItems() {
        return this.getItems().filter((item) => item.pinned);
    }
    /**
     * Gets the non-pinned items in this column.
     *
     * @public
     * @returns Array of non-pinned FlowBoardColumnItemElement.
     */
    getNonPinnedItems() {
        return this.getItems().filter((item) => !item.pinned);
    }
    /**
     * Sets the pinned state with event support.
     *
     * @public
     * @param pinned The new pinned state.
     */
    setPinned(pinned) {
        if (this._pinned === pinned) {
            return;
        }
        const beforeDetail = {
            columnKey: this._columnKey,
            pinned: pinned,
            cancel: false
        };
        this._flowBoardBeforeColumnPinChange.emit(beforeDetail);
        if (beforeDetail.cancel) {
            return;
        }
        this._pinned = pinned;
        this.requestUpdate('pinned');
        this._flowBoardColumnPinChange.emit({
            columnKey: this._columnKey,
            pinned: pinned
        });
    }
    /**
     * Handles slot changes to update empty state and sync drag refs.
     *
     * @internal
     */
    handleSlotChange() {
        this.updateHasItems();
        if (this.isDragEnabled) {
            this.syncItemDragRefs();
        }
    }
    onPinnedChanged(_prev, _next) {
        // Update host attributes for styling
        if (this._pinned) {
            this.setAttribute('pinned', '');
        }
        else {
            this.removeAttribute('pinned');
        }
    }
    updateHasItems() {
        const items = this.getItems();
        const hadItems = this._hasItems;
        this._hasItems = items.length > 0;
        if (hadItems !== this._hasItems) {
            this.requestUpdate();
        }
    }
};
__decorate([
    Attribute({
        type: String
    }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], FlowBoardColumnElement.prototype, "columnKey", null);
__decorate([
    Attribute({ type: Boolean }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], FlowBoardColumnElement.prototype, "reorderable", null);
__decorate([
    Attribute({ type: Boolean }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], FlowBoardColumnElement.prototype, "pinned", null);
__decorate([
    Watch('pinned'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Boolean, Boolean]),
    __metadata("design:returntype", void 0)
], FlowBoardColumnElement.prototype, "onPinnedChanged", null);
FlowBoardColumnElement = FlowBoardColumnElement_1 = __decorate([
    Component({
        selector: 'mosaik-flow-board-column',
        template: flowBoardColumnElementTemplate,
        themes: {
            joy: flowBoardColumnElementJoyStyle,
            memphis: flowBoardColumnElementMemphisStyle,
            cosmopolitan: flowBoardColumnElementCosmopolitanStyle
        },
        imports: [
            FlowBoardColumnItemElement,
            FlowBoardColumnItemComposerElement
        ]
    }),
    __metadata("design:paramtypes", [])
], FlowBoardColumnElement);
export { FlowBoardColumnElement };
//# sourceMappingURL=FlowBoardColumnElement.js.map