{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/widgets.html.twig" as widgets %}

{% block page_title %}{{ 'calendar'|trans }}{% endblock %}
{% block page_actions %}
    {% set event = actions(app.user, 'calendar', 'index') %}
    {{ widgets.page_actions(event.actions) }}
{% endblock %}

{% block main %}
    <div class="row">
        {% set hasTwoColumns = (config.dragDropAmount > 0 and dragAndDrop is not empty and (dragAndDrop|filter(s => s.entries|length > 0)|length > 0)) or form is not null %}
        {% if hasTwoColumns %}
        <div class="hidden-xs col-sm-5 col-md-4 col-lg-3 no-print">
            {% if form is not null %}
                {% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
                    {% block box_body %}
                        {{ form_start(form) }}
                        {{ form_widget(form) }}
                        {{ form_end(form) }}
                    {% endblock %}
                {% endembed %}
            {% endif %}
            {% for source in dragAndDrop|filter(s => s.entries|length > 0) %}
                {% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
                    {% block box_title %}{{ source.title|trans }}{% endblock %}
                    {% block box_body_class %}drag-and-drop-source{% endblock %}
                    {% block box_body %}
                        <div class="external-events" data-method="{{ source.method }}" data-route="{{ path(source.route, source.routeParams) }}" data-route-replacer="{{ source.routeReplacer|json_encode|e('html_attr') }}">
                            {% for entry in source.entries|slice(0, config.dragDropAmount) %}
                                <div draggable="true" style="background-color: {{ entry.color }}; color: {{ entry.color|font_contrast }}" class="external-event ui-draggable ui-draggable-handle" data-entry="{{ entry.data|json_encode|e('html_attr') }}"{% if entry.project is not null %} data-toggle="tooltip" title="{{ entry.project.customer.name }}"{% endif %}>
                                    {% if source.blockInclude is not null and entry.blockName is not null and block(entry.blockName, source.blockInclude) is defined %}
                                        {{ block(entry.blockName, source.blockInclude) }}
                                    {% else %}
                                        <span class="title">{{ entry.title }}</span>
                                    {% endif %}
                                </div>
                            {% endfor %}
                        </div>
                    {% endblock %}
                {% endembed %}
            {% endfor %}
        </div>
        {% endif %}

        <div class="col-xs-12 {% if hasTwoColumns %}col-sm-7 col-md-8 col-lg-9 col-print-12{% endif %}">
            {% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
                {% block box_body_class %}no-padding{% endblock %}
                {% block box_body %}
                    <div id="timesheet_calendar"></div>
                {% endblock %}
            {% endembed %}
        </div>
    </div>
{% endblock %}

{% block stylesheets %}
    {{ parent() }}
    {{ encore_entry_link_tags('calendar') }}
{% endblock %}

{% block head %}
    {{ parent() }}
    {{ encore_entry_script_tags('calendar') }}
{% endblock %}

{% block javascripts %}
    {% set calendarSelector = '#timesheet_calendar' %}
    {% set createParams = '' %}
    {% set createRoute = 'timesheet_create' %}
    {% set editRoute = 'timesheet_edit' %}
    {% set canDelete = is_granted('delete_own_timesheet') %}
    {% set canCreate = is_granted('create_own_timesheet') %}
    {% set canEdit = is_granted('edit_own_timesheet') %}
    {% set isForeignEdit = false %}
    {% if user != app.user %}
        {% set isForeignEdit = true %}
        {% set createParams = '&user=' ~ user.id %}
        {% set createRoute = 'admin_timesheet_create' %}
        {% set editRoute = 'admin_timesheet_edit' %}
        {% set canDelete = is_granted('delete_other_timesheet') %}
        {% set canCreate = is_granted('create_other_timesheet') %}
        {% set canEdit = is_granted('edit_other_timesheet') %}
    {% endif %}

    {{ parent() }}
    <script>
        activatePopover();

        document.addEventListener('kimai.initialized', function() {
            KimaiReloadPageWidget.create('kimai.systemConfigUpdate', true);
        });

        document.addEventListener('kimai.timesheetUpdate', function() {
            jQuery('{{ calendarSelector }}').fullCalendar('refetchEvents');
        });

        {# https://gomakethings.com/dynamically-changing-the-text-color-based-on-background-color-contrast-with-vanilla-js/ #}
        function calculateFontContrastColor(hexcolor)
        {
            if (hexcolor.slice(0, 1) === '#') {
                hexcolor = hexcolor.slice(1);
            }

            if (hexcolor.length === 3) {
                hexcolor = hexcolor.split('').map(function (hex) { return hex + hex; }).join('');
            }

            let r = parseInt(hexcolor.substr(0,2),16);
            let g = parseInt(hexcolor.substr(2,2),16);
            let b = parseInt(hexcolor.substr(4,2),16);
            let yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;

            return (yiq >= 128) ? '#000000' : '#ffffff';
        }

        function convertApiTimesheetToCalendar(apiItem)
        {
            const defaultColor = kimai.getConfiguration().get('defaultColor');
            let color = apiItem.activity.color;
            if (color === null || color === defaultColor) {
                color = apiItem.project.color;
                if (color === null || color === defaultColor) {
                    color = apiItem.project.customer.color;
                }
            }
            if (color == null) {
                color = defaultColor;
            }

            let title = apiItem.activity.name;

            let description = '';
            if (apiItem.description !== null && apiItem.description !== '') {
                description = '{{ constant('\\App\\Form\\Type\\CalendarTitlePatternType::SPACER') }}' + apiItem.description;
            }

            {% if config.entryTitlePattern == constant('\\App\\Form\\Type\\CalendarTitlePatternType::PATTERN_PROJECT') %}
                title = apiItem.project.name;
            {% elseif config.entryTitlePattern == constant('\\App\\Form\\Type\\CalendarTitlePatternType::PATTERN_CUSTOMER') %}
                title = apiItem.project.customer.name;
            {% elseif config.entryTitlePattern == constant('\\App\\Form\\Type\\CalendarTitlePatternType::PATTERN_DESCRIPTION') %}
                title = apiItem.description;
            {% elseif config.entryTitlePattern == constant('\\App\\Form\\Type\\CalendarTitlePatternType::PATTERN_ACTIVITY_DESCRIPTION') %}
                title = apiItem.activity.name + description;
            {% elseif config.entryTitlePattern == constant('\\App\\Form\\Type\\CalendarTitlePatternType::PATTERN_PROJECT_DESCRIPTION') %}
                title = apiItem.project.name + description;
            {% elseif config.entryTitlePattern == constant('\\App\\Form\\Type\\CalendarTitlePatternType::PATTERN_CUSTOMER_DESCRIPTION') %}
                title = apiItem.project.customer.name + description;
            {% endif %}

            if (title === '' || title === null) {
                title = apiItem.activity.name;
            }

            return {
                id: apiItem.id,
                title: title,
                description: apiItem.description,
                start: apiItem.begin,
                end: apiItem.end,
                activity: apiItem.activity.name,
                project: apiItem.project.name,
                customer: apiItem.project.customer.name,
                tags: apiItem.tags,
                color: color,
                textColor: calculateFontContrastColor(color),
            };
        }

        function renderEventPopoverTitle(eventObj)
        {
            return eventObj.start.format('L') + ' | ' + eventObj.start.format('LT') + ' - ' + (eventObj.end ? eventObj.end.format('LT') : '');
        }

        function renderEventPopoverContent(eventObj)
        {
            const escaper = kimai.getPlugin('escape');

            return '<div class="calendar-entry">' +
                    '<ul>' +
                        '<li>' + '{{ 'label.customer'|trans }}: ' + escaper.escapeForHtml(eventObj.customer) + '</li>' +
                        '<li>' + '{{ 'label.project'|trans }}: ' + escaper.escapeForHtml(eventObj.project) + '</li>' +
                        '<li>' + '{{ 'label.activity'|trans }}: ' + escaper.escapeForHtml(eventObj.activity) + '</li>' +
                    '</ul>' +
                    (eventObj.description !== null || eventObj.tags.length > 0 ? '<hr>' : '') +
                    (eventObj.description ? '<p>' + eventObj.description + '</p>' : '') +
                    (eventObj.tags !== null && eventObj.tags.length > 0 ? '<span class="badge bg-green">' + eventObj.tags.join('</span> <span class="badge bg-green">') + '</span>' : '') +
                '</div>'
            ;
        }

        function showPopover()
        {
            return window._hidePopovers === false;
        }

        function activatePopover()
        {
            window._hidePopovers = false;
        }

        function deactivatePopover()
        {
            window._hidePopovers = true;
        }

        function hidePopover()
        {
            jQuery('.popover').popover('hide');
        }

        let changeHandler = function(event, delta, revertFunc) {
            let updateUrl = '{{ path('patch_timesheet', {id: '-XX-'}) }}'.replace('-XX-', event.id);
            let API = kimai.getPlugin('api');
            let ALERT = kimai.getPlugin('alert');

            let payload = {'begin': event.start.format()};

            if (event.end !== null && event.end !== undefined) {
                payload.end = event.end.format();
            } else {
                payload.end = null;
            }

            API.patch(updateUrl, JSON.stringify(payload), function(result) {
                ALERT.success('action.update.success');
            }, function(xhr, err) {
                const callback = API.getPatchErrorHandler();
                revertFunc();
                callback(xhr, err);
            });
        };

        document.addEventListener('kimai.initialized', function(event) {
            // prevent multiple open popovers
            jQuery('html').on('click', function(e) {
                jQuery('.popover').each(function() {
                    if(jQuery(e.target).parents(".fc-time-grid-event").get(0) !== $(this).prev().get(0)) {
                        jQuery(this).popover('hide');
                    }
                });
            });

            {# convert HTML to draggable items #}
            jQuery('.external-events .external-event').each(function () {
                {# FullCalendar 3 can only work with jQuery UI elements #}
                jQuery(this).draggable({
                    zIndex        : 1070,
                    revert        : true,   {# will cause the event to go back to its #}
                    revertDuration: 0       {# original position after the drag #}
                });
            });

            let kimai = event.detail.kimai;
            let API = kimai.getPlugin('api');
            let DATES = kimai.getPlugin('date');
            jQuery('{{ calendarSelector }}').fullCalendar({
                themeSystem: 'bootstrap3',
                defaultView: '{{ app.user.getPreferenceValue('calendar.initial_view') }}',
                {% if google is not null %}
                googleCalendarApiKey: '{{ google.apiKey }}',
                {% endif %}
                header    : {
                    left  : 'prev,next today{% if canDelete %} deleteButton{% endif %}',
                    center: 'title',
                    right : 'month,agendaWeek,agendaDay'
                },
                dragRevertDuration: 0,
                eventLimit: {{ config.dayLimit }},
                weekNumbersWithinDays: true,
                weekNumberCalculation: 'ISO',
                weekNumbers: {% if config.showWeekNumbers %}true{% else %}false{% endif %},
                allDaySlot: false,
                navLinks: true,
                locale: kimai.getConfiguration().get('locale').replace('_', '-').toLowerCase(),
                firstDay: kimai.getConfiguration().get('first_dow_iso'),
                customButtons: {
                    deleteButton: {
                        text: '{{ 'action.delete'|trans }}',
                        click: function() {
                            kimai.getPlugin('alert').info('{{ 'calendar.drag_and_drop.delete'|trans }}');
                        }
                    }
                },
                height: 'auto',
                nowIndicator: true,
                now: '{{ now|date_format('c') }}',
                {# see https://github.com/kevinpapst/kimai2/issues/2155 #}
                timezone: '{{ app.user.timezone == 'UTC' ? 'GMT' : app.user.timezone }}',
                weekends: {% if config.showWeekends %}true{% else %}false{% endif %},
                businessHours: {
                    dow: [{{ config.businessDays|join(',') }}],
                    start: '{{ config.businessTimeBegin }}',
                    end: '{{ config.businessTimeEnd }}'
                },
                slotDuration: '{{ config.slotDuration }}',
                slotLabelInterval: '{{ config.slotDuration }}',
                minTime: '{{ config.timeframeBegin }}',
                maxTime: '{{ config.timeframeEnd }}',
                defaultTimedEventDuration: '{{ config.slotDuration }}',  {# how long should entries look like when they don't have an end #}
                droppable: true,
                {# drop function handles external draggable events #}
                drop: function (date, jsEvent, ui, resourceId) {
                    let entry = jsEvent.target;
                    let source = entry.parentElement;
                    let plainData = entry.dataset.entry;
                    let data = JSON.parse(plainData);
                    {% if isForeignEdit and canCreate %}
                        data.user = {{ user.id }};
                    {% endif %}
                    let urlReplacer = JSON.parse(source.dataset.routeReplacer);
                    let apiUrl = source.dataset.route;

                    for (const [key, value] of Object.entries(urlReplacer)) {
                        apiUrl = apiUrl.replace(key, data[value]);
                    }

                    let view = jQuery('{{ calendarSelector }}').fullCalendar('getView');
                    let begin = date.clone();

                    {#
                        FIXME some tracking modes do not allow to set the time

                        public function canEditEnd(): bool;
                        public function canEditDuration(): bool;
                        public function canUpdateTimesWithAPI(): bool;

                    #}

                    {% if not can_edit_begin %}
                        begin.time('{{ defaultStartTime }}');
                    {% endif %}

                    if (view.name === 'month' && !begin.hasTime()) {
                        begin.time('{{ defaultStartTime }}');
                    }

                    let end = begin.clone();
                    end.add(moment.duration('{{ config.slotDuration }}'));

                    {% if not is_punch_mode %}
                        {% if can_edit_begin %}
                            data.begin = begin.format();
                        {% endif %}
                        {% if can_edit_end %}
                            data.end = end.format();
                        {% endif %}
                    {% endif %}

                    if (source.dataset.method === 'PATCH') {
                        API.patch(
                            apiUrl,
                            JSON.stringify(data),
                            function (result) {
                                kimai.getPlugin('alert').success('action.update.success');
                                let newItem = convertApiTimesheetToCalendar(result);
                                jQuery('{{ calendarSelector }}').fullCalendar('renderEvent', newItem);
                            }
                        );
                    } else {
                        API.post(
                            apiUrl,
                            JSON.stringify(data),
                            function (result) {
                                kimai.getPlugin('alert').success('action.update.success');
                                let newItem = convertApiTimesheetToCalendar(result);
                                jQuery('{{ calendarSelector }}').fullCalendar('renderEvent', newItem);
                            }
                        );
                    }
                },
                eventSources: [
                    {
                        events: function(start, end, timezone, callback) {
                            let from = moment(start.format()).format(moment.HTML5_FMT.DATETIME_LOCAL_SECONDS);
                            let to = moment(end.format()).format(moment.HTML5_FMT.DATETIME_LOCAL_SECONDS);
                            API.get('{{ path('get_timesheets') }}?user={{ user.id }}&size=1000&full=true&begin='+from+'&end='+to, {}, function(result) {
                                let apiEvents = [];
                                for (const record of result) {
                                    apiEvents.push(convertApiTimesheetToCalendar(record));
                                }
                                callback(apiEvents);
                            });
                        },
                        color: '{{ config('theme.calendar.background_color') }}',
                        name: 'kimaiUserTimeSource'
                    }
                    {% if google is not null %}
                        {% for source in google.sources %}
                        ,
                        {
                            googleCalendarId: '{{ source.uri }}',
                            name: '{{ source.id }}',
                            color: '{{ source.color }}',
                            textColor: '{{ source.color|font_contrast }}',
                            editable: false
                        }
                        {% endfor %}
                    {% endif %}
                ],
                eventRender: function(eventObj, $el, view) {
                    {# don't show popover for google calendar #}
                    if (eventObj.source.ajaxSettings !== undefined) {
                        return;
                    }

                    {# or when an event is dragged or resized #}
                    if (!showPopover()) {
                        return;
                    }

                    if (view.name !== 'month' ) {
                        jQuery(".fc-dailytotal").text(DATES.formatSeconds(0)).data('seconds', 0).data('ids', '');
                    }

                    hidePopover();
                    $el.popover({
                        title: renderEventPopoverTitle(eventObj),
                        content: renderEventPopoverContent(eventObj),
                        trigger: 'hover',
                        placement: 'auto',
                        container: 'body',
                        html: true
                    });
                },
                viewRender: function(view, element) {
                    if (view.name === 'month') {
                        return;
                    }

                    {# allowed in agendaWeek and agendaDay #}
                    jQuery(".fc-day-header").each(function (key, val) {
                        var $this = jQuery(this);
                        var dateYMD = $this.attr("data-date");
                        $this.append('<div class="fc-dailytotal" data-seconds="0" data-ids="" id="dailytotal-' + dateYMD + '">'+DATES.formatSeconds(0)+'</div>');
                    });
                },
                eventAfterRender: function(event, element, view) {
                    {# allowed in agendaWeek and agendaDay #}
                    if (view.name === 'month') {
                        return;
                    }

                    {# TODO calculate duration for running entries #}
                    if (event.end === null) {
                        return;
                    }

                    {# TODO split day entries are calculated only for the begin date #}
                    var $element = jQuery("#dailytotal-" + moment(event.start).format("YYYY-MM-DD"));
                    var ids = $element.data('ids');
                    if (ids === null || ids === undefined) {
                        ids = '';
                    }

                    if (ids.indexOf(event.id) !== -1) {
                        return;
                    }

                    var prev = $element.data('seconds');
                    var duration = prev + ((event.end - event.start) / 1000);
                    $element.data('seconds', duration);
                    $element.data('ids', event.id + ' ' + ids);
                    $element.text(DATES.formatSeconds(duration));
                },
                {% if not is_punch_mode and canCreate %}
                    dayClick: function(date, jsEvent, view) {
                        {#
                           Day-clicks are always triggered, unless a selection was created.
                           So clicking in a day (month view) or any slot (week and day view) will trigger a dayClick
                           BEFORE triggering a select - make sure not two create dialogs are requested
                        #}
                        if (view.type !== 'month') {
                            return;
                        }

                        let createUrl = '{{ path(createRoute) }}?begin=' + date.format() + '{{ createParams|raw }}';
                        kimai.getPlugin('modal').openUrlInModal(createUrl);
                    },
                    selectable: true,
                    select: function(start, end, jsEvent, view) {
                        if(view.type === 'month') {
                            {#
                               Multi-day clicks are NOT allowed in the month view, as simple day clicks would also trigger
                               a select - there is no way to distinguish a simple click and a two day selection
                            #}
                            return;
                        }
                        let createUrl = '{{ path(createRoute) }}' + '?from=' + start.format() + '&to=' + end.format() + '{{ createParams|raw }}';
                        kimai.getPlugin('modal').openUrlInModal(createUrl);
                    },
                {% endif %}
                {% if canEdit %}
                    eventClick: function(eventObj, jsEvent, view) {
                        if (eventObj.source.ajaxSettings !== undefined) {
                            jsEvent.preventDefault();
                            return;
                        }
                        let editUrl = '{{ path(editRoute, {id: '-XX-'}) }}'.replace('-XX-', eventObj.id);
                        kimai.getPlugin('modal').openUrlInModal(editUrl);
                    },
                    {% if not is_punch_mode %}
                        editable: true,
                        eventDragStart: function(event, jsEvent, ui, view) {
                            deactivatePopover();
                        },
                        eventDragStop: function(event, jsEvent, ui, view) {
                            activatePopover();
                            {% if canDelete %}
                                var trash = jQuery('.fc-deleteButton-button');
                                var offset = trash.offset();

                                if (jsEvent.pageX >= offset.left && jsEvent.pageX<= (offset.left + trash.outerWidth(true)) &&
                                    jsEvent.pageY >= offset.top && jsEvent.pageY <= (offset.top + trash.outerHeight(true))) {
                                    API.delete(
                                        '{{ path('delete_timesheet', {'id': '__xxx__'}) }}'.replace('__xxx__', event.id),
                                        function () {
                                            kimai.getPlugin('alert').success('action.delete.success');
                                            jQuery('{{ calendarSelector }}').fullCalendar('removeEvents', event._id);
                                        }, function () {
                                            kimai.getPlugin('alert').success('action.delete.error');
                                        }
                                    );
                                }
                            {% endif %}
                        },
                        eventDrop: changeHandler,
                        eventResizeStart: function(event, jsEvent, ui, view) {
                            deactivatePopover();
                        },
                        eventResizeStop: function(event, jsEvent, ui, view) {
                            activatePopover();
                        },
                        eventResize: changeHandler,
                    {% endif %}
                {% endif %}
            });
            var trashBtn = jQuery('.fc-deleteButton-button');
            trashBtn.html('<span class="text-danger"><i class="{{ 'trash'|icon }} text-danger"></i> ' + trashBtn.text() + '</span>');
        });
    </script>
{% endblock %}