// #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 } from '@breadstone/mosaik-elements';
import { Emit } from '../../../../../../events/Decorators/EmitDecorator';
import { formatDateToIso, getDayKey } from '../../../../../../Extensions/DateExtensions';
import { Appearanceable, IAppearanceableProps } from '../../../../../Behaviors/Appearanceable';
import { Disableable, IDisableableProps } from '../../../../../Behaviors/Disableable';
import { ILocaleableProps, Localeable } from '../../../../../Behaviors/Localeable';
import { ISizeableProps, Sizeable } from '../../../../../Behaviors/Sizeable';
import { IThemeableProps, Themeable } from '../../../../../Behaviors/Themeable';
import { IVariantableProps, Variantable } from '../../../../../Behaviors/Variantable';
import { addInheritanceConsumerController } from '../../../../../Controllers/InheritanceConsumerController';
import { Attribute } from '../../../../../Decorators/AttributeDecorator';
import { Property } from '../../../../../Decorators/PropertyDecorator';
import { DayOfWeek } from '../../../../../Types/DayOfWeek';
import { CustomElement } from '../../../../Abstracts/CustomElement';
import { ISchedulerElementProps } from '../../ISchedulerElementProps';
import { SCHEDULER_INHERITANCE_CONTEXT } from '../../SchedulerInheritanceContext';
/**
 * Default values for SchedulerViewBaseElement properties.
 *
 * @public
 */
export var ISchedulerViewBaseElementProps;
(function (ISchedulerViewBaseElementProps) {
    ISchedulerViewBaseElementProps.DEFAULTS = {
        startDate: null,
        firstDayOfWeek: DayOfWeek.Sunday,
        blackoutDates: [],
        specialDates: [],
        isTodayHighlighted: false,
        isWeekendHighlighted: false,
        collectedEvents: [],
        appearance: IAppearanceableProps.DEFAULTS.appearance,
        variant: IVariantableProps.DEFAULTS.variant,
        locale: ILocaleableProps.DEFAULTS.locale,
        themeName: IThemeableProps.DEFAULTS.themeName,
        size: ISizeableProps.DEFAULTS.size,
        disabled: IDisableableProps.DEFAULTS.disabled,
        weekdayFormat: ISchedulerElementProps.DEFAULTS.weekdayFormat,
        dayFormat: ISchedulerElementProps.DEFAULTS.dayFormat,
        timeFormat: ISchedulerElementProps.DEFAULTS.timeFormat,
        monthDayFormat: ISchedulerElementProps.DEFAULTS.monthDayFormat
    };
})(ISchedulerViewBaseElementProps || (ISchedulerViewBaseElementProps = {}));
/**
 * Scheduler View Base Element - The foundational base class for all scheduler view components.
 *
 * @description
 * SchedulerViewBaseElement provides the core infrastructure for all scheduler view types including
 * month, week, day, and agenda views. It manages common scheduler functionality such as date range
 * navigation, event collection rendering, blackout dates, special dates, visual highlighting, and
 * user interactions like event activation and range selection. The class implements inheritance
 * controllers to consume properties from parent SchedulerElement, supports comprehensive i18n and
 * locale formatting, and provides cancelable events for interaction workflows. All concrete scheduler
 * views (MonthView, WeekView, DayView, AgendaView) extend this base class to inherit consistent
 * behavior, theming, and event handling patterns.
 *
 * @remarks
 * This class uses the InheritanceConsumerController to inherit properties (disabled, appearance,
 * variant, size, locale, etc.) from a parent SchedulerElement when nested. Watch methods are
 * intentionally not implemented to allow subclasses full control over change reactions. Event
 * activation and range selection provide before/after event pairs with cancellation support.
 *
 * @name SchedulerViewBaseElement
 * @category Abstract Elements
 *
 * @slot [dynamic] - Slots are defined by concrete scheduler view implementations
 *
 * @csspart [dynamic] - Parts are defined by concrete scheduler view implementations
 *
 * @fires connected {ConnectedEvent} - Emitted when the element is connected to the DOM
 * @fires disconnected {DisconnectedEvent} - Emitted when the element is disconnected from the DOM
 * @fires changed {PropertyChangedEvent} - Emitted when any attribute changes before update
 * @fires schedulerBeforeEventActivate {SchedulerBeforeEventActivateEvent} - Emitted before an event is activated (cancelable)
 * @fires schedulerEventActivate {SchedulerEventActivateEvent} - Emitted after an event is activated
 * @fires schedulerBeforeSelectRange {SchedulerBeforeSelectRangeEvent} - Emitted before a range is selected (cancelable)
 * @fires schedulerSelectRange {SchedulerSelectRangeEvent} - Emitted after a range is selected
 *
 * @example
 * Extending SchedulerViewBaseElement for a month view:
 * ```typescript
 * export class SchedulerMonthViewElement extends SchedulerViewBaseElement {
 *   public override get view(): SchedulerView {
 *     return SchedulerView.Month;
 *   }
 *
 *   protected override render() {
 *     return html`<div class="month-grid">...</div>`;
 *   }
 * }
 * ```
 *
 * @example
 * Using blackout and special dates:
 * ```html
 * <mosaik-scheduler-month-view
 *   start-date="2024-03-01"
 *   .blackoutDates="${[new Date('2024-03-15'), new Date('2024-03-20')]}"
 *   .specialDates="${[new Date('2024-03-10')]}"
 *   is-today-highlighted
 *   is-weekend-highlighted>
 * </mosaik-scheduler-month-view>
 * ```
 *
 * @example
 * Handling event activation with cancellation:
 * ```typescript
 * view.schedulerBeforeEventActivate.on((detail) => {
 *   if (!isUserAuthorized(detail.eventKey)) {
 *     detail.cancel = true; // Prevent activation
 *   }
 * });
 *
 * view.schedulerEventActivate.on((detail) => {
 *   console.log('Event activated:', detail.eventKey);
 * });
 * ```
 *
 * @example
 * Custom date formatting:
 * ```html
 * <mosaik-scheduler-week-view
 *   weekday-format="ddd"
 *   day-format="d"
 *   time-format="h:mm tt"
 *   month-day-format="MMM dd">
 * </mosaik-scheduler-week-view>
 * ```
 *
 * @abstract
 * @public
 */
export class SchedulerViewBaseElement extends Themeable(Sizeable(Appearanceable(Variantable(Localeable(Disableable(CustomElement)))))) {
    // #region Fields
    _inheritance;
    _schedulerBeforeEventActivate;
    _schedulerEventActivate;
    _schedulerBeforeSelectRange;
    _schedulerSelectRange;
    _startDate;
    _firstDayOfWeek;
    _blackoutDates;
    _specialDates;
    _isTodayHighlighted;
    _isWeekendHighlighted;
    _collectedEvents;
    _intl;
    _weekdayFormat;
    _dayFormat;
    _timeFormat;
    _monthDayFormat;
    // #endregion
    // #region Ctor
    /**
     * @public
     */
    constructor() {
        super();
        this._inheritance = addInheritanceConsumerController(this, {
            context: SCHEDULER_INHERITANCE_CONTEXT
        });
        // addInheritanceProviderController<ISchedulerViewInherited>(this, {
        //     context: SCHEDULER_VIEW_INHERITANCE_CONTEXT,
        //     values: () => ({
        //         view: this.view
        //     })
        // });
        this._startDate = ISchedulerViewBaseElementProps.DEFAULTS.startDate;
        this._firstDayOfWeek = ISchedulerViewBaseElementProps.DEFAULTS.firstDayOfWeek;
        this._blackoutDates = ISchedulerViewBaseElementProps.DEFAULTS.blackoutDates;
        this._specialDates = ISchedulerViewBaseElementProps.DEFAULTS.specialDates;
        this._isTodayHighlighted = ISchedulerViewBaseElementProps.DEFAULTS.isTodayHighlighted;
        this._isWeekendHighlighted = ISchedulerViewBaseElementProps.DEFAULTS.isWeekendHighlighted;
        this._collectedEvents = ISchedulerViewBaseElementProps.DEFAULTS.collectedEvents;
        this._weekdayFormat = ISchedulerViewBaseElementProps.DEFAULTS.weekdayFormat;
        this._dayFormat = ISchedulerViewBaseElementProps.DEFAULTS.dayFormat;
        this._timeFormat = ISchedulerViewBaseElementProps.DEFAULTS.timeFormat;
        this._monthDayFormat = ISchedulerViewBaseElementProps.DEFAULTS.monthDayFormat;
        this._intl = null;
        this._schedulerBeforeEventActivate = new HTMLElementEventEmitter(this, 'schedulerBeforeEventActivate');
        this._schedulerEventActivate = new HTMLElementEventEmitter(this, 'schedulerEventActivate');
        this._schedulerBeforeSelectRange = new HTMLElementEventEmitter(this, 'schedulerBeforeSelectRange');
        this._schedulerSelectRange = new HTMLElementEventEmitter(this, 'schedulerSelectRange');
    }
    /**
     * @public
     * @override
     */
    get disabled() {
        return this._inheritance.get('disabled', super.disabled);
    }
    set disabled(value) {
        this._inheritance.markExplicit('disabled');
        super.disabled = value;
    }
    /**
     * @public
     * @override
     */
    get appearance() {
        return this._inheritance.get('appearance', super.appearance);
    }
    set appearance(value) {
        this._inheritance.markExplicit('appearance');
        super.appearance = value;
    }
    /**
     * @public
     * @override
     */
    get variant() {
        return this._inheritance.get('variant', super.variant);
    }
    set variant(value) {
        this._inheritance.markExplicit('variant');
        super.variant = value;
    }
    /**
     * @public
     * @override
     */
    get size() {
        return this._inheritance.get('size', super.size);
    }
    set size(value) {
        this._inheritance.markExplicit('size');
        super.size = value;
    }
    /**
     * @public
     * @override
     */
    get locale() {
        return this._inheritance.get('locale', super.locale);
    }
    set locale(value) {
        this._inheritance.markExplicit('locale');
        super.locale = value;
    }
    /**
     * @public
     * @override
     */
    get dir() {
        return this._inheritance.get('dir', super.dir);
    }
    set dir(value) {
        this._inheritance.markExplicit('dir');
        super.dir = value;
    }
    /**
     * @public
     * @override
     */
    get themeName() {
        return this._inheritance.get('themeName', super.themeName);
    }
    set themeName(value) {
        this._inheritance.markExplicit('themeName');
        super.themeName = value;
    }
    /**
     * Gets or sets the start date for the visible range.
     *
     * @public
     * @attr
     */
    get startDate() {
        return this._inheritance.get('startDate', this._startDate);
    }
    set startDate(value) {
        this._inheritance.markExplicit('startDate');
        if (this._startDate !== value) {
            this._startDate = value;
            this.requestUpdate('startDate');
        }
    }
    /**
     * Gets the effective start date, defaulting to today if startDate is null.
     *
     * @protected
     * @readonly
     */
    get effectiveStartDate() {
        return this.startDate ?? new Date();
    }
    /**
     * Gets or sets the first day of the week.
     *
     * @public
     * @attr
     */
    get firstDayOfWeek() {
        return this._inheritance.get('firstDayOfWeek', this._firstDayOfWeek);
    }
    set firstDayOfWeek(value) {
        this._inheritance.markExplicit('firstDayOfWeek');
        if (this._firstDayOfWeek !== value) {
            this._firstDayOfWeek = value;
            this.requestUpdate('firstDayOfWeek');
        }
    }
    /**
     * Gets or sets the blackout dates that should be disabled.
     *
     * @public
     */
    get blackoutDates() {
        return this._inheritance.get('blackoutDates', this._blackoutDates);
    }
    set blackoutDates(value) {
        this._inheritance.markExplicit('blackoutDates');
        if (this._blackoutDates !== value) {
            this._blackoutDates = value;
            this.requestUpdate('blackoutDates');
        }
    }
    /**
     * Gets or sets the special dates that should be highlighted.
     *
     * @public
     */
    get specialDates() {
        return this._inheritance.get('specialDates', this._specialDates);
    }
    set specialDates(value) {
        this._inheritance.markExplicit('specialDates');
        if (this._specialDates !== value) {
            this._specialDates = value;
            this.requestUpdate('specialDates');
        }
    }
    /**
     * Gets or sets whether today is highlighted.
     *
     * @public
     * @attr
     */
    get isTodayHighlighted() {
        return this._inheritance.get('isTodayHighlighted', this._isTodayHighlighted);
    }
    set isTodayHighlighted(value) {
        this._inheritance.markExplicit('isTodayHighlighted');
        if (this._isTodayHighlighted !== value) {
            this._isTodayHighlighted = value;
            this.requestUpdate('isTodayHighlighted');
        }
    }
    /**
     * Gets or sets whether weekends are highlighted.
     *
     * @public
     * @attr
     */
    get isWeekendHighlighted() {
        return this._inheritance.get('isWeekendHighlighted', this._isWeekendHighlighted);
    }
    set isWeekendHighlighted(value) {
        this._inheritance.markExplicit('isWeekendHighlighted');
        if (this._isWeekendHighlighted !== value) {
            this._isWeekendHighlighted = value;
            this.requestUpdate('isWeekendHighlighted');
        }
    }
    /**
     * Gets or sets the collected events to display.
     *
     * @public
     */
    get collectedEvents() {
        return this._collectedEvents;
    }
    set collectedEvents(value) {
        if (this._collectedEvents !== value) {
            this._collectedEvents = value;
            this.requestUpdate('collectedEvents');
        }
    }
    /**
     * Gets or sets the internationalization helper.
     *
     * @public
     */
    get intl() {
        return this._inheritance.get('intl', this._intl);
    }
    set intl(value) {
        this._inheritance.markExplicit('intl');
        if (this._intl !== value) {
            this._intl = value;
            this.requestUpdate('intl');
        }
    }
    /**
     * Gets or sets the format string for weekday headers.
     *
     * @remarks
     * Supports: `d` (day number 1-7), `dd` (01-07), `ddd` (Mon), `dddd` (Monday).
     * Default: `ddd`.
     *
     * @public
     * @attr
     */
    get weekdayFormat() {
        return this._inheritance.get('weekdayFormat', this._weekdayFormat);
    }
    set weekdayFormat(value) {
        this._inheritance.markExplicit('weekdayFormat');
        if (this._weekdayFormat !== value) {
            this._weekdayFormat = value;
            this.requestUpdate('weekdayFormat');
        }
    }
    /**
     * Gets or sets the format string for day numbers.
     *
     * @remarks
     * Supports: `d` (1-31), `dd` (01-31).
     * Default: `d`.
     *
     * @public
     * @attr
     */
    get dayFormat() {
        return this._inheritance.get('dayFormat', this._dayFormat);
    }
    set dayFormat(value) {
        this._inheritance.markExplicit('dayFormat');
        if (this._dayFormat !== value) {
            this._dayFormat = value;
            this.requestUpdate('dayFormat');
        }
    }
    /**
     * Gets or sets the format string for time display.
     *
     * @remarks
     * Supports: `H` (0-23), `HH` (00-23), `h` (1-12), `hh` (01-12), `m` (0-59), `mm` (00-59), `tt` (AM/PM).
     * Default: `HH:mm`.
     *
     * @public
     * @attr
     */
    get timeFormat() {
        return this._inheritance.get('timeFormat', this._timeFormat);
    }
    set timeFormat(value) {
        this._inheritance.markExplicit('timeFormat');
        if (this._timeFormat !== value) {
            this._timeFormat = value;
            this.requestUpdate('timeFormat');
        }
    }
    /**
     * Gets or sets the format string for month-day display.
     *
     * @remarks
     * Supports: `M` (1-12), `MM` (01-12), `MMM` (Jan), `MMMM` (January), `d` (1-31), `dd` (01-31).
     * Default: `MMM d`.
     *
     * @public
     * @attr
     */
    get monthDayFormat() {
        return this._inheritance.get('monthDayFormat', this._monthDayFormat);
    }
    set monthDayFormat(value) {
        this._inheritance.markExplicit('monthDayFormat');
        if (this._monthDayFormat !== value) {
            this._monthDayFormat = value;
            this.requestUpdate('monthDayFormat');
        }
    }
    /**
     * Called before an event is activated (cancelable).
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get schedulerBeforeEventActivate() {
        return this._schedulerBeforeEventActivate;
    }
    /**
     * Called after an event is activated.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get schedulerEventActivate() {
        return this._schedulerEventActivate;
    }
    /**
     * Called before a range is selected (cancelable).
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get schedulerBeforeSelectRange() {
        return this._schedulerBeforeSelectRange;
    }
    /**
     * Called after a range is selected.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get schedulerSelectRange() {
        return this._schedulerSelectRange;
    }
    // #endregion
    // #region Methods
    /**
     * Returns true when a date is configured as blackout date.
     *
     * @public
     * @param date - The date to check.
     */
    isBlackoutDate(date) {
        const normalizedBlackoutDates = this._blackoutDates.length === 0
            ? new Set()
            : new Set(this._blackoutDates.map((d) => formatDateToIso(d)));
        return normalizedBlackoutDates.has(getDayKey(date));
    }
    /**
     * Returns true when a date is configured as special date.
     *
     * @public
     * @param date - The date to check.
     */
    isSpecialDate(date) {
        const normalizedSpecialDates = this._specialDates.length === 0
            ? new Set()
            : new Set(this._specialDates.map((d) => formatDateToIso(d)));
        return normalizedSpecialDates.has(getDayKey(date));
    }
    /**
     * Returns true when the given date is weekend.
     *
     * @public
     * @param date - The date to check.
     */
    isWeekend(date) {
        const dayOfWeek = date.getDay();
        return dayOfWeek === 0 || dayOfWeek === 6;
    }
    /**
     * Returns true when the given date is today.
     *
     * @public
     * @param date - The date to check.
     */
    isToday(date) {
        return getDayKey(date) === formatDateToIso(new Date());
    }
    /**
     * Activates an event programmatically.
     *
     * @public
     * @param eventKey - The event key to activate.
     * @param trigger - The activation trigger.
     * @returns True if activation succeeded.
     */
    activateEvent(eventKey, trigger = 'click') {
        const beforeDetail = {
            eventKey,
            trigger,
            cancel: false
        };
        this._schedulerBeforeEventActivate.emit(beforeDetail);
        if (beforeDetail.cancel) {
            return false;
        }
        this._schedulerEventActivate.emit({
            eventKey,
            trigger
        });
        return true;
    }
    /**
     * Handles click on an event renderer.
     *
     * @private
     */
    onEventClick(event, eventKey) {
        event.stopPropagation();
        this.activateEvent(eventKey, 'click');
    }
    /**
     * Handles keyboard activation of an event.
     *
     * @private
     */
    onEventKeydown(event, eventKey) {
        if (event.key === 'Enter' || event.key === ' ') {
            event.preventDefault();
            this.activateEvent(eventKey, 'keyboard');
        }
    }
    /**
     * Emits a select range event.
     *
     * @protected
     * @param start - The start date.
     * @param end - The end date.
     * @param dayKey - The day key (YYYY-MM-DD).
     * @param isAllDay - Whether this is an all-day selection.
     */
    emitSelectRange(start, end, dayKey, isAllDay) {
        const beforeDetail = {
            start,
            end,
            dayKey,
            isAllDay,
            cancel: false
        };
        this._schedulerBeforeSelectRange.emit(beforeDetail);
        if (!beforeDetail.cancel) {
            this._schedulerSelectRange.emit({
                start,
                end,
                dayKey,
                isAllDay
            });
        }
    }
}
__decorate([
    Attribute({
        type: Date,
        converter: {
            fromAttribute: (value) => value ? new Date(value) : null,
            toAttribute: (value) => value ? value.toISOString().split('T')[0] : ''
        }
    }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [Object])
], SchedulerViewBaseElement.prototype, "startDate", null);
__decorate([
    Attribute({ type: DayOfWeek }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], SchedulerViewBaseElement.prototype, "firstDayOfWeek", null);
__decorate([
    Property({ type: Array }),
    __metadata("design:type", Array),
    __metadata("design:paramtypes", [Array])
], SchedulerViewBaseElement.prototype, "blackoutDates", null);
__decorate([
    Property({ type: Array }),
    __metadata("design:type", Array),
    __metadata("design:paramtypes", [Array])
], SchedulerViewBaseElement.prototype, "specialDates", null);
__decorate([
    Attribute({ type: Boolean, useDefault: true }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], SchedulerViewBaseElement.prototype, "isTodayHighlighted", null);
__decorate([
    Attribute({ type: Boolean, useDefault: true }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], SchedulerViewBaseElement.prototype, "isWeekendHighlighted", null);
__decorate([
    Property({ type: Array }),
    __metadata("design:type", Array),
    __metadata("design:paramtypes", [Array])
], SchedulerViewBaseElement.prototype, "collectedEvents", null);
__decorate([
    Property({ type: Object }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [Object])
], SchedulerViewBaseElement.prototype, "intl", null);
__decorate([
    Attribute({ type: String, useDefault: true }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], SchedulerViewBaseElement.prototype, "weekdayFormat", null);
__decorate([
    Attribute({ type: String, useDefault: true }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], SchedulerViewBaseElement.prototype, "dayFormat", null);
__decorate([
    Attribute({ type: String, useDefault: true }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], SchedulerViewBaseElement.prototype, "timeFormat", null);
__decorate([
    Attribute({ type: String, useDefault: true }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], SchedulerViewBaseElement.prototype, "monthDayFormat", null);
__decorate([
    Emit({ eventName: 'schedulerBeforeEventActivate' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], SchedulerViewBaseElement.prototype, "schedulerBeforeEventActivate", null);
__decorate([
    Emit({ eventName: 'schedulerEventActivate' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], SchedulerViewBaseElement.prototype, "schedulerEventActivate", null);
__decorate([
    Emit({ eventName: 'schedulerBeforeSelectRange' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], SchedulerViewBaseElement.prototype, "schedulerBeforeSelectRange", null);
__decorate([
    Emit({ eventName: 'schedulerSelectRange' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], SchedulerViewBaseElement.prototype, "schedulerSelectRange", null);
//# sourceMappingURL=SchedulerViewBaseElement.js.map