import { Calendar, EventClickArg, EventSourceInput } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import multiMonthPlugin from '@fullcalendar/multimonth';
import { makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { dateRangeStrToDates } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { StrCast } from '../../../../fields/Types';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { FieldView, FieldViewProps } from '../FieldView';

type CalendarView = 'month' | 'multi-month' | 'week';

@observer
export class CalendarBox extends ViewBoxBaseComponent<FieldViewProps>() {
    public static LayoutString(fieldKey: string = 'calendar') {
        return FieldView.LayoutString(CalendarBox, fieldKey);
    }

    constructor(props: FieldViewProps) {
        super(props);
        makeObservable(this);
    }

    componentDidMount(): void {}

    componentWillUnmount(): void {}

    _calendarRef = React.createRef<HTMLElement>();

    get dateRangeStr() {
        return StrCast(this.Document.date_range);
    }

    // Choose a calendar view based on the date range
    get calendarViewType(): CalendarView {
        const [fromDate, toDate] = dateRangeStrToDates(this.dateRangeStr);

        if (fromDate.getFullYear() !== toDate.getFullYear() || fromDate.getMonth() !== toDate.getMonth()) return 'multi-month';

        if (Math.abs(fromDate.getDay() - toDate.getDay()) > 7) return 'month';
        return 'week';
    }

    get calendarStartDate() {
        return this.dateRangeStr.split('|')[0];
    }

    get calendarToDate() {
        return this.dateRangeStr.split('|')[1];
    }

    get childDocs(): Doc[] {
        return this.childDocs; // get all sub docs for a calendar
    }

    docBackgroundColor(type: string): string {
        // TODO: Return a different color based on the event type
        return 'blue';
    }

    get calendarEvents(): EventSourceInput | undefined {
        if (this.childDocs.length === 0) return undefined;
        return this.childDocs.map((doc, idx) => {
            const docTitle = StrCast(doc.title);
            const docDateRange = StrCast(doc.date_range);
            const [startDate, endDate] = dateRangeStrToDates(docDateRange);
            const docType = doc.type;
            const docDescription = doc.description ? StrCast(doc.description) : '';

            return {
                title: docTitle,
                start: startDate,
                end: endDate,
                allDay: false,
                classNames: [StrCast(docType)], // will determine the style
                editable: false, // subject to change in the future
                backgroundColor: this.docBackgroundColor(StrCast(doc.type)),
                color: 'white',
                extendedProps: {
                    description: docDescription,
                },
            };
        });
    }

    handleEventClick = (arg: EventClickArg) => {
        // TODO: open popover with event description, option to open CalendarManager and change event date, delete event, etc.
    };

    calendarEl: HTMLElement = document.getElementById('calendar-box-v1')!;

    // https://fullcalendar.io
    get calendar() {
        return new Calendar(this.calendarEl, {
            plugins: [this.calendarViewType === 'multi-month' ? multiMonthPlugin : dayGridPlugin],
            headerToolbar: {
                left: 'prev,next today',
                center: 'title',
                right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek',
            },
            initialDate: this.calendarStartDate,
            navLinks: true,
            editable: false,
            displayEventTime: false,
            displayEventEnd: false,
            events: this.calendarEvents,
            eventClick: this.handleEventClick,
        });
    }

    render() {
        return (
            <div className="calendar-box-conatiner">
                <div id="calendar-box-v1"></div>
            </div>
        );
    }
}
