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;
};
import { MelodicComponent } from '@melodicdev/core';
import { toIsoDate, parseDate, addDays, addMonths, startOfWeek, getMonthGrid, getWeekColumns, getDayColumn, getWeekdayHeaders, getISOWeekNumber, formatMonthYear, formatDateRange, getMonthAbbrev, getDayName, getEventsForDate, getTimeSlots, getMonthGrid as getMiniGrid, getMiniCalendarDots } from './calendar-view.utils.js';
import { calendarViewTemplate } from './calendar-view.template.js';
import { calendarViewStyles } from './calendar-view.styles.js';
/**
 * ml-calendar-view - Full-featured calendar component with month, week, and day views
 *
 * @example
 * ```html
 * <ml-calendar-view .events=${events} view="month"></ml-calendar-view>
 * ```
 *
 * @fires ml:view-change - Emitted when the view mode changes. Detail: { view }
 * @fires ml:date-change - Emitted when the navigated date changes. Detail: { date }
 * @fires ml:event-click - Emitted when a calendar event is clicked. Detail: { event }
 * @fires ml:date-click - Emitted when a date cell is clicked. Detail: { date }
 * @fires ml:add-event - Emitted when the add event button is clicked. Detail: { date? }
 */
let CalendarViewComponent = class CalendarViewComponent {
    constructor() {
        /** Current view mode */
        this.view = 'month';
        /** Navigated date (ISO date string) */
        this.date = '';
        /** Day the week starts on (0=Sunday, 1=Monday) */
        this.weekStartsOn = 0;
        /** Maximum visible events per day cell in month view */
        this.maxVisibleEvents = 3;
        /** Label for the add event button */
        this.addButtonText = 'Add event';
        /** Hide prev/next navigation arrows */
        this.hideNav = false;
        /** Hide the "Today" button */
        this.hideTodayButton = false;
        /** Hide the view dropdown */
        this.hideViewSelector = false;
        /** Hide the add event button */
        this.hideAddButton = false;
        /** Calendar events (property-only) */
        this.events = [];
        /** Whether the view dropdown is open */
        this.isViewDropdownOpen = false;
        /** Mini calendar state for day view sidebar */
        this._miniCalYear = 0;
        this._miniCalMonth = 0;
        this._hasScrolledToTime = false;
        this._boundCloseDropdown = null;
        /* ── Navigation handlers ── */
        this.navigatePrev = () => {
            const d = this._currentDate;
            let next;
            if (this.view === 'month') {
                next = addMonths(d, -1);
            }
            else if (this.view === 'week') {
                next = addDays(d, -7);
            }
            else {
                next = addDays(d, -1);
            }
            this.setDate(next);
        };
        this.navigateNext = () => {
            const d = this._currentDate;
            let next;
            if (this.view === 'month') {
                next = addMonths(d, 1);
            }
            else if (this.view === 'week') {
                next = addDays(d, 7);
            }
            else {
                next = addDays(d, 1);
            }
            this.setDate(next);
        };
        this.goToToday = () => {
            this.setDate(new Date());
        };
        /* ── View dropdown ── */
        this.toggleViewDropdown = () => {
            this.isViewDropdownOpen = !this.isViewDropdownOpen;
        };
        this.setView = (view) => {
            this.view = view;
            this.isViewDropdownOpen = false;
            this._hasScrolledToTime = false;
            this.elementRef.dispatchEvent(new CustomEvent('ml:view-change', {
                bubbles: true,
                composed: true,
                detail: { view }
            }));
        };
        /* ── Event handlers ── */
        this.handleEventClick = (event) => {
            this.elementRef.dispatchEvent(new CustomEvent('ml:event-click', {
                bubbles: true,
                composed: true,
                detail: { event }
            }));
        };
        this.handleDateClick = (iso) => {
            this.elementRef.dispatchEvent(new CustomEvent('ml:date-click', {
                bubbles: true,
                composed: true,
                detail: { date: iso }
            }));
        };
        this.handleAddEvent = () => {
            this.elementRef.dispatchEvent(new CustomEvent('ml:add-event', {
                bubbles: true,
                composed: true,
                detail: {}
            }));
        };
        this.handleAddEventOnDate = (iso) => {
            this.elementRef.dispatchEvent(new CustomEvent('ml:add-event', {
                bubbles: true,
                composed: true,
                detail: { date: iso }
            }));
        };
        this.showMoreEvents = (iso) => {
            // Switch to day view for the date
            this.date = iso;
            this.setView('day');
        };
        /* ── Mini calendar handlers ── */
        this.miniCalPrevMonth = () => {
            if (this._miniCalMonth === 0) {
                this._miniCalMonth = 11;
                this._miniCalYear--;
            }
            else {
                this._miniCalMonth--;
            }
        };
        this.miniCalNextMonth = () => {
            if (this._miniCalMonth === 11) {
                this._miniCalMonth = 0;
                this._miniCalYear++;
            }
            else {
                this._miniCalMonth++;
            }
        };
        this.handleMiniCalSelect = (iso) => {
            this.setDate(parseDate(iso));
        };
    }
    /** Check if header-left slot has consumer content */
    get hasHeaderLeftSlot() {
        return this.elementRef?.querySelector('[slot="header-left"]') !== null;
    }
    /** Check if header-actions slot has consumer content */
    get hasHeaderActionsSlot() {
        return this.elementRef?.querySelector('[slot="header-actions"]') !== null;
    }
    // Current date object derived from the `date` attribute
    get _currentDate() {
        if (this.date)
            return parseDate(this.date);
        return new Date();
    }
    onCreate() {
        // Initialize date if not set
        if (!this.date) {
            const now = new Date();
            this.date = toIsoDate(now.getFullYear(), now.getMonth(), now.getDate());
        }
        // Init mini cal to current date's month
        const d = this._currentDate;
        this._miniCalYear = d.getFullYear();
        this._miniCalMonth = d.getMonth();
        // Close dropdown on outside click
        this._boundCloseDropdown = (e) => {
            if (!this.isViewDropdownOpen)
                return;
            const path = e.composedPath();
            const shadow = this.elementRef.shadowRoot;
            if (!shadow)
                return;
            const dropdown = shadow.querySelector('.ml-cv__view-dropdown');
            if (dropdown && !path.includes(dropdown)) {
                this.isViewDropdownOpen = false;
            }
        };
        document.addEventListener('click', this._boundCloseDropdown, true);
    }
    onDestroy() {
        if (this._boundCloseDropdown) {
            document.removeEventListener('click', this._boundCloseDropdown, true);
        }
    }
    onRender() {
        // Auto-scroll time grid to ~6 AM on initial load
        if ((this.view === 'week' || this.view === 'day') && !this._hasScrolledToTime) {
            const shadow = this.elementRef.shadowRoot;
            if (!shadow)
                return;
            const scrollEl = shadow.querySelector('.ml-cv__time-scroll');
            if (scrollEl) {
                // 6 AM = row 12 (at 30-min increments), each row is 40px
                scrollEl.scrollTop = 12 * 40;
                this._hasScrolledToTime = true;
            }
        }
    }
    /* ── Header computed getters ── */
    get todayMonthAbbrev() {
        return getMonthAbbrev(new Date());
    }
    get todayDayNumber() {
        return new Date().getDate();
    }
    get headerTitle() {
        return formatMonthYear(this._currentDate);
    }
    get weekNumber() {
        return getISOWeekNumber(this._currentDate);
    }
    get headerSubtitle() {
        if (this.view === 'month') {
            return `Week ${this.weekNumber}`;
        }
        if (this.view === 'week') {
            const start = startOfWeek(this._currentDate, this.weekStartsOn);
            const end = addDays(start, 6);
            return formatDateRange(start, end);
        }
        // day view
        return getDayName(this._currentDate);
    }
    get currentIsoDate() {
        const d = this._currentDate;
        return toIsoDate(d.getFullYear(), d.getMonth(), d.getDate());
    }
    /* ── Month view getters ── */
    get weekdayHeaders() {
        return getWeekdayHeaders(this.weekStartsOn);
    }
    get monthGrid() {
        const d = this._currentDate;
        const grid = getMonthGrid(d.getFullYear(), d.getMonth(), this.weekStartsOn);
        // Populate events for each day cell
        for (const cell of grid) {
            cell.events = getEventsForDate(this.events, cell.iso);
        }
        return grid;
    }
    /* ── Week view getters ── */
    get weekColumns() {
        return getWeekColumns(this._currentDate, this.weekStartsOn, this.events);
    }
    get timeSlots() {
        return getTimeSlots();
    }
    /* ── Day view getters ── */
    get dayColumn() {
        return getDayColumn(this._currentDate, this.events);
    }
    get dayEvents() {
        return getEventsForDate(this.events, this.currentIsoDate);
    }
    get dayViewDateLabel() {
        const d = this._currentDate;
        return d.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' });
    }
    /* ── Mini calendar getters (day view sidebar) ── */
    get miniCalendarTitle() {
        return formatMonthYear(new Date(this._miniCalYear, this._miniCalMonth, 1));
    }
    get miniCalendarWeekdays() {
        return getWeekdayHeaders(this.weekStartsOn).map((h) => h.short.charAt(0));
    }
    get miniCalendarGrid() {
        return getMiniGrid(this._miniCalYear, this._miniCalMonth, this.weekStartsOn);
    }
    get miniCalendarDots() {
        return getMiniCalendarDots(this._miniCalYear, this._miniCalMonth, this.events);
    }
    /* ── Private helpers ── */
    setDate(d) {
        this.date = toIsoDate(d.getFullYear(), d.getMonth(), d.getDate());
        this._miniCalYear = d.getFullYear();
        this._miniCalMonth = d.getMonth();
        this.elementRef.dispatchEvent(new CustomEvent('ml:date-change', {
            bubbles: true,
            composed: true,
            detail: { date: this.date }
        }));
    }
};
CalendarViewComponent = __decorate([
    MelodicComponent({
        selector: 'ml-calendar-view',
        template: calendarViewTemplate,
        styles: calendarViewStyles,
        attributes: [
            'view',
            'date',
            'week-starts-on',
            'max-visible-events',
            'add-button-text',
            'hide-nav',
            'hide-today-button',
            'hide-view-selector',
            'hide-add-button'
        ]
    })
], CalendarViewComponent);
export { CalendarViewComponent };
