
//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//
// Calendar functions
//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//


var CalendarInitialView = "dayGridMonth";

function CreateFullCalendar(CalendarElement, EventsJsonString) {

    //https://fullcalendar.io/docs
    //https://fullcalendar.io/docs/initialize-globals
    //https://fullcalendar.io/docs/event-object

    var events = JSON.parse(EventsJsonString);

    // Find the calendar div html element
    var calendarEl = CalendarElement.get(0);
    var calendar = new FullCalendar.Calendar(calendarEl, {
        themeSystem: 'bootstrap5',
        initialView: CalendarInitialView,
        selectable: true,
        editable: true,
        height: "99%",
        dayMaxEventRows: true,
        navLinks: true,
        views: {
            timeGrid: {
                dayMaxEventRows: 4 // adjust to 4 only for timeGridWeek/timeGridDay
            },
            twelveMonthGrid: {
                buttonText: 'year',
                type: 'multiMonth',
                duration: { months: 12 },
                monthMode: true,
                fixedWeekCount: false,
            },
        },
        headerToolbar: {
                left: 'prev,next today',
                center: 'title',
                right: 'twelveMonthGrid,dayGridMonth,timeGridWeek,timeGridDay'
        },
        eventClick: function (info) { OnCalendarEventClick(info); },
        eventDrop: function (info) { OnCalendarEventDrop(info); },
        eventResize: function (info) { OnCalendarEventResize(info); },
        eventMouseEnter: function (info) { info.el.title = info.event.title + "\r\n" + info.event.start; },

        eventDidMount: (arg) => {
            const eventId = arg.event.id;
            OnCalendarEventRender(arg);
            arg.el.addEventListener("contextmenu", (jsEvent) => {
                jsEvent.preventDefault();
                OnCalendarEventRightClick(arg.event, eventId);
                //console.log("contextMenu", eventId);
            })
        },

        dateClick: function (info) { OnCalendarDateClick(info); },

        viewDidMount: function (info) { OnCalendarViewDidMount(info); },

        //eventDidMount: function (info) {
        //    $(info.el).tooltip({
        //        title: /*info.event.start.toISOString().split('T')[1] + " - " + */info.event.title,
        //        container: 'body',
        //        delay: { "show": 50, "hide": 50 }
        //    });
        //},
        events: events,
    //    events: [
    //        {
    //            title: 'All Day Event',
    //            start: '2022-07-01'
    //        },
    //        {
    //            title: 'Long Event',
    //            start: '2022-04-07',
    //            end: '2022-07-10'
    //        },
    //    ]
    });
    calendar.render();
}


function OnCalendarEventClick(info) {

    //https://fullcalendar.io/docs/eventClick
    //eventClickInfo is a plain object with the following properties:

    //event
    //The associated Event Object.

    //el
    //The HTML element for this event.

    //jsEvent
    //The native JavaScript event with low - level information such as click coordinates.

    //view
    //The current View Object.


    //alert('Event: ' + info.event.title);

    // Content values
    var id = info.event.id;
    const IdPartsArray = id.split("~");
    if (!IdPartsArray)
        return;
    if (IdPartsArray.length < 3)
        return;

    var ContentType = IdPartsArray[0];
    var RecordTableName = IdPartsArray[1];
    var RecordId = IdPartsArray[2];

    if (RecordTableName && RecordId) {
        $('input[id="HiddenSelectedDataTypeId"]').val(ContentType);
        $('input[id="HiddenSelectedTableId"]').val(RecordTableName);
        $('input[id="HiddenSelectedRecordId"]').val(RecordId);

        RefreshPropertyGridViewFromHiddenSelection($("#" + PropertyGridPartialViewDivId));
    }
}


function OnCalendarEventRightClick(calendarevt, id) {

    const IdPartsArray = id.split("~");
    if (!IdPartsArray)
        return;
    if (IdPartsArray.length < 3)
        return;

    var ContentType = IdPartsArray[0];
    var RecordTableName = IdPartsArray[1];
    var RecordId = IdPartsArray[2];

    if (RecordTableName && RecordId) {
        $('input[id="HiddenSelectedDataTypeId"]').val(ContentType);
        $('input[id="HiddenSelectedTableId"]').val(RecordTableName);
        $('input[id="HiddenSelectedRecordId"]').val(RecordId);

        // Open content menu
        AjaxGetObjectContextMenu(event, $(this), ContentType, RecordTableName, RecordId, null/*sSelectedCellDbTable*/, null/*sSelectedCellDbColumn*/);

        RefreshPropertyGridViewFromHiddenSelection($("#" + PropertyGridPartialViewDivId));
    }
}


var LastCalendarDateClick = new Date();

function OnCalendarDateClick(info) {

    if (!info)
        return;

    //console.log("OnCalendarDateClick");

    // Ugly check for dblclick
    var CalendarDateClick = new Date();
    var ClickDiffMs = Math.abs(CalendarDateClick - LastCalendarDateClick);
    LastCalendarDateClick = CalendarDateClick;
    if (ClickDiffMs < 500) {

        // Add one second to prevent triple-click
        LastCalendarDateClick.setSeconds(LastCalendarDateClick.getSeconds() + 1);

        OnCalendarDateDblClick(info);
        return;
    }
}

function OnCalendarDateDblClick(info) {
    // Crate a new record

    //console.log("OnCalendarDateDblClick");

    setTimeout(function () { OnCreateNewContentRecord(info.dateStr); }, 500);
}



function OnCalendarEventRender(info) {

    if (!info || !info.event)
        return;

    //console.log("OnCalendarEventRender");

    // Add icon to event title
    // Icon is stored in extendedProps as a base64 url
    // Add <img> tag to event title element
    if (info.event.extendedProps) {

        // Event icon
        var sIconBase64Url = info.event.extendedProps.iconbase64url;
        if (sIconBase64Url) {
            if (info.event.allDay)
                $(info.el).find('span:first').prepend('<img src="' + sIconBase64Url + '" />');
            else
                $(info.el).find('.fc-event-title').prepend('<img src="' + sIconBase64Url + '" />');
        }
    }
}




function OnCalendarEventDrop(info) {

    //https://fullcalendar.io/docs/eventDrop
    //eventDropInfo is a plain object with the following properties:

    //event
    //An Event Object that holds information about the event(date, title, etc) after the drop.

    //relatedEvents	an array of other related Event Objects that were also dropped.an event might have other recurring event instances or might be linked to other events with the same groupId
    //oldEvent
    //An Event Object that holds information about the event before the drop.

    //oldResource
    //If the resource has changed, this is the Resource Object the event came from.If the resource has not changed, this will be undefined.For use with the resource plugins only.

    //newResource
    //If the resource has changed, this is the Resource Object the event went to.If the resource has not changed, this will be undefined.For use with the resource plugins only.

    //delta
    //A Duration Object that represents the amount of time the event was moved by.

    //revert
    //A function that, if called, reverts the event’s start / end date to the values before the drag.This is useful if an ajax call should fail.

    //view
    //The current View Object.

    //el
    //The HTML element that was dragged.

    //jsEvent
    //The native JavaScript event with low - level information such as click coordinates.

    //This callback is fired before the eventChange callback is fired.

    //eventDrop does not get called when an external event lands on the calendar.eventReceive is called instead.


    //alert(info.event.title + " was dropped on " + info.event.start.toISOString());

    OnMoveEventRecord(info);
}


function OnCalendarEventResize(info) {

    //https://fullcalendar.io/docs/eventResizeStop
    //This callback is guaranteed to be triggered after the user resizes an event, even if the event doesn’t change in duration.It is triggered before the event’s information has been modified(if changed in duration) and before the eventResize callback is triggered.

    //info is a plain object with the following properties:

    //event
    //An Event Object that holds information about the event(date, title, etc) before the drop.

    //jsEvent
    //The native JavaScript event with low - level information such as click coordinates.

    //view
    //The current View Object.

    OnMoveEventRecord(info);
}


//function OnSchedulerAppointmentSelected(evt, ui) {

//    if (!ui)
//        return;
//    if (!ui.selectedAppointment)
//        return;
//    if (!ui.selectedAppointment._e)
//        return;
//    if (!ui.selectedAppointment._e.id)
//        return;

//    var Scheduler = ui.owner;
//    var SelectedAppointment = ui.selectedAppointment;
//    var ViewMode = ui.viewMode;
//    var DateSelected = ui.selectedInDate;

//    // Content values
//    var id = SelectedAppointment._e.id;
//    const IdPartsArray = id.split("~");
//    if (!IdPartsArray)
//        return;
//    if (IdPartsArray.length < 3)
//        return;

//    var ContentType = IdPartsArray[0];
//    var RecordTableName = IdPartsArray[1];
//    var RecordId = IdPartsArray[2];

//    if (RecordTableName && RecordId) {
//        $('input[id="HiddenSelectedDataTypeId"]').val(ContentType);
//        $('input[id="HiddenSelectedTableId"]').val(RecordTableName);
//        $('input[id="HiddenSelectedRecordId"]').val(RecordId);

//        RefreshPropertyGridViewFromHiddenSelection($("#" + PropertyGridPartialViewDivId));
//    }
//}


function OnMoveEventRecord(EventInfo) {

    if (!EventInfo)
        return;
    if (!EventInfo.event)
        return;
    if (!EventInfo.event.id)
        return;

    // Content values
    var id = EventInfo.event.id;
    const IdPartsArray = id.split("~");
    if (!IdPartsArray)
        return;
    if (IdPartsArray.length < 3)
        return;

    var ContentType = IdPartsArray[0];
    var RecordTableName = IdPartsArray[1];
    var RecordId = IdPartsArray[2];
    var sStartDate = EventInfo.event.start.toISOString();
    var sEndDate = sStartDate;
    if (EventInfo.event && EventInfo.event.end)
        sEndDate = EventInfo.event.end.toISOString();

    if (RecordTableName && RecordId) {
        $('input[id="HiddenSelectedDataTypeId"]').val(ContentType);
        $('input[id="HiddenSelectedTableId"]').val(RecordTableName);
        $('input[id="HiddenSelectedRecordId"]').val(RecordId);

        AjaxMoveRecord(ContentType, RecordTableName, RecordId, sStartDate, sEndDate);
    }
}

function AjaxMoveRecord(ContentType, sDbTable, sRecordId, sStartDate, sEndDate) {

    if (!ContentType)
        return;
    if (!sDbTable)
        return;
    if (!sRecordId)
        return;

    var params = {
        "ContentType": ContentType,
        "DbTable": sDbTable,
        "RecordId": sRecordId,
        "StartDate": sStartDate,
        "EndDate": sEndDate,
    };

    $.ajax({
        url: VirtualDirectory + "/Home/AjaxMoveRecord",
        type: "POST",
        data: JSON.stringify(params),
        contentType: "application/json",
        success: function (response) {
            if (response.Success) {
                RefreshPropertyGridViewFromHiddenSelection($("#" + PropertyGridPartialViewDivId));
            }
            else {
                ToastError("AjaxMoveRecord", response.ErrorResults);
            }
        },
        error: function (xhr, status, error) {
            var errormsg = "Error " + xhr.status + ", " + xhr.statusText + "\r\nText: " + sStartDate;
            ToastError("AjaxMoveRecord", errormsg);
            console.log('AJAX: ' + errormsg);
        }
    });
}





/**
 * The calendar view has just been loaded or changed
 * @param {any} info
 * @returns
 */
function OnCalendarViewDidMount(info) {

    // https://fullcalendar.io/docs/view-render-hooks
    // Argument
    // When the above hooks are specified as a function in the form function(arg), the arg is an object with the following properties:
    // view - a View Object
    // el - the view’s root HTML element.not available in viewClassNames

    if (!info)
        return;
    if (!info.view)
        return;

    // Remember the view type for the next time the calendar is rendered
    CalendarInitialView = info.view.type;
    if (!CalendarInitialView)
        CalendarInitialView = "dayGridMonth";
}
