/**
 * UMD (Universal Module Definition) to support CommonJS, AMD and browser
 * Thanks to https://github.com/umdjs/umd
 */
(function(factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        // Node/CommonJS
        module.exports = function(root, jQuery) {
            if (jQuery === undefined) {
                // require('jQuery') returns a factory that requires window to
                // build a jQuery instance, we normalize how we use modules
                // that require this pattern but the window provided is a noop
                // if it's defined (how jquery works)
                if (typeof window !== 'undefined') {
                    jQuery = require('jquery');
                } else {
                    jQuery = require('jquery')(root);
                }
            }
            factory(jQuery);
            return jQuery;
        };
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function($) {
    "use strict";

    // locally assign window
    var w = window;

    var igCalendar = function() {
        var self = this;
        /* define the context menu */
        this.contextMenuConfig = {
            // define which elements trigger this menu
            selector: ".button-menu",
            trigger: 'left',
            build: function($trigger, e) {
                e.preventDefault();
                return {
                    items: window.igCalendar.getItems($trigger, self)
                };
            }
        };
        this.getContextMenuConfig = function() {
            return this.contextMenuConfig;
        }
        /* prepare the command (ajax call): get arguments/url from given arguments */
        this.getCommand = function(controller, action, calendar, date, timeslot, reservation, event, timeslots) {
            var $calendar = $('.calendar-' + calendar);
            var $date = $('.calendar-date-' + date, $calendar);
            return {
                name: action,
                url: $calendar.data('url'),
                loading: $calendar.data('loading'),
                set: {
                    //dateFormat: $trigger.parents('.calendar-date').data('dateFormat'),
                    //dateDay: $trigger.parents('.calendar-date').data('dateDay')
                    dateFormat: $date.data('dateFormat'),
                    dateDay: $date.data('dateDay')
                },
                args: {
                    action: action,
                    controller: controller,
                    calendar: calendar,
                    timeslot: timeslot,
                    date: date,
                    reservation: reservation,
                    event: event,
                    timeslots: timeslots
                }
            };
        }
        /* prepare the command (ajax call): get arguments/url from data attributes of element*/
        this.getCommandElement = function(controller, action, $trigger) {
            var calendar = $trigger.data('calendar');
            var date = $trigger.data('date');
            var timeslot = $trigger.data('timeslot');
            var reservation = $trigger.data('reservation');
            var event = $trigger.data('event');
            var timeslots = self.getSelectedTimeslotUids($trigger.parents('.calendar-entries'));
            if(!timeslots.length) {
                timeslots.push(timeslot);
            }
            return this.getCommand(controller, action, calendar, date, timeslot, reservation, event, timeslots);
        }
        /* prepare the command (ajax call): get arguments/url from form elements */
        this.getCommandForm = function(controller, action, $form) {
            var calendar = $('input[name="calendar"]', $form).val();
            var timeslot = $('input[name="timeslot"]', $form).val();
            var reservation = null;
            var event = null;
            var date = $('input[name="date"]', $form).val();
            var timeslots = [];
            $('input[name="timeslots[]"]').each(function() {
                timeslots.push($(this).val());
            });
            if(!timeslots.length) {
                timeslots.push(timeslot);
            }
            return this.getCommand(controller, action, calendar, date, timeslot, reservation, event, timeslots);
        }
        /* init fancyBox after show: init select2 and prepare submit of form */
        this.fancyboxAfterShow = function(instance, current, target) {
            $('.select2', current.$content).select2();
            IGDATAPOOLFE.addForm($('.dp-form', current.$content).get(0), 'lightbox');

            if($('#reservations-hasBillAddress', current.$content).length) {
                var $billAddressField = $('#reservations-hasBillAddress', current.$content);
                if($billAddressField.is(':checked')) {
                    $('.bill-field', current.$content).addClass('show');
                }
                $billAddressField.on('change', function(e) {
                    $('.bill-field', current.$content).removeClass('show');
                    if($(this).is(':checked')) {
                        $('.bill-field', current.$content).addClass('show');
                    }
                });
            }

            $('form', current.$content).unbind('submit');
            $('form .fancyElement', current.$content).each(function() {
                if ($(this).val() != '') {
                    $(this).parents('.fancyInput').addClass('clicked');
                }
            });
            $('form', current.$content).submit(
                function(event) {
                    event.preventDefault();
		    var noErrors = window.validateReservationForm();
		    if (!noErrors) {
			return false;
		    }
                    var command = self.getCommandForm('Ajax', 'reservationCreate', event.target);
                    self.callCommandWithForm(command, $(target), $(this));
                    parent.jQuery.fancybox.getInstance().close();
                }
            );
        }

	
        /* open fancyBox with content of an inline element, and set some content and values */
        this.fancyboxOpenInline = function(command) {
            var boxId = '#tx-ig-reservations-ajax-calendar-' + command.args.calendar + '-' + command.name;
            $.fancybox.open({
                src: boxId,
                type: 'inline',
                opts: {
                    afterShow: function(instance, current) {
                        // IE11 nicht + scriptmerger gehts nicht
                        //for (let [key, value] of Object.entries(command.args))
                        $.each(command.args, function(key, value) {
                            $('input[name="' + key + '"]', event.target).val(value);
                        });
                        $.each(command.set, function(key, value) {
                            $('.set-' + key + '', event.target).html(value);
                        });
                        self.fancyboxAfterShow(instance, current, '#timeslot-' + command.args.calendar + '-' + command.args.date + '-' + command.args.timeslot);
                    }
                }
            });
        }

        /* open fancyBox with ajax respnse */
        this.fancyboxOpenAjaxCommand = function(command) {
            $.ajax({
                url: command.url,
                method: 'post',
                dataType: "json",
                data: {
                    "tx_igreservations_ajax": command.args
                },
                success: function(data) {
                    // on success, post (preview) returned data in fancybox	    //context: document.body
                    $.fancybox.open(data.html, {
                        // fancybox API options
                        fitToView: true,
                        afterShow: function(instance, current) {
                            self.fancyboxAfterShow(instance, current, '#timeslot-' + command.args.calendar + '-' + command.args.date + '-' + command.args.timeslot)
                        }
                    });
                }
            });
        }

        /* call a Command */
        this.callCommandWithArgs = function(command, $container, additionalArgs) {
            var args = command.args;
            $.each(additionalArgs, function(key, value) {
                args[key] = value;
            });
            this.callCommand(command, $container, {
                "tx_igreservations_ajax": args
            });
        }
        /* call a Command */
        this.callCommandWithForm = function(command, $container, $form) {
            command.url = $form.attr('action');
            this.callCommand(command, $container, $form.serialize());
        }

        /* call a Command */
        this.callCommand = function(command, $container, data) {
            //var calendarUid= $calendar.data('calendar');
            $container.html(command.loading); // icon: spinner-circle
            $.ajax({
                url: command.url,
                method: 'post',
                dataType: "json",
                data: data
                //context: document.body
            }).done(
                function(msg) {
                    var $newContent = $(msg.html);

                    $container.replaceWith($newContent);


                    // Update data-index for timeslot selection
                    $newContent.parents('.calendar-entries').find('.timeslot').each(function(index) {
                        $(this).data('index', index);
                        $(this).attr('data-index', index);
                    });

                    // activate click actions and context menu
                    $('.tx-ig-reservations-ajax-command', $newContent).click(self.ajaxCommand);
                    $container.contextMenu(self.contextMenuConfig);
                    toastr.options = {
                        "closeButton": true
                    };
                    if (msg.error) {
                        //$newContent.hasClass('ajax-error')
                        toastr.options.timeOut = 0; // Show errors forever
                    }
                    toastr[msg.toast.type](msg.toast.message, msg.toast.title);
                }
            );
        }

        /* Click event of ajax command */
        this.ajaxCommand = function(event) {
            event.preventDefault();
            var $element = $(this);
            var confirmTitle = $element.data('confirmTitle');
            var confirmContent = $element.data('confirmContent');
            if (confirmContent || confirmTitle) {
                var confirmButtonOkText = $element.data('confirmButtonOkText');
                var confirmButtonCancelText = $element.data('confirmButtonCancelText');
                var confirmButtonOkClass = $element.data('confirmButtonOkClass');
                var confirmButtonCancelClass = $element.data('confirmButtonCancelClass');
                $.confirm({
                    title: confirmTitle ? confirmTitle : '',
                    content: confirmContent,
                    buttons: {
                        confirm: {
                            useBootstrap: false,
                            text: confirmButtonOkText ? confirmButtonOkText : 'Ok',
                            btnClass: confirmButtonOkClass ? confirmButtonOkClass : 'btn-ok',
                            action: function() {
                                self.elementAjaxCommand($element);
                            }
                        },
                        cancel: {
                            text: confirmButtonCancelText ? confirmButtonCancelText : 'Abbrechen',
                            btnClass: confirmButtonCancelClass ? confirmButtonCancelClass : 'btn-cancel',
                        }
                    }
                });
            } else {
                self.elementAjaxCommand($element);
            }
        }
        /* Call ajax command */
        this.elementAjaxCommand = function($el) {
            var command = this.getCommandElement($el.data('controller'), $el.data('action'), $el);
            if ($el.data('lightbox') == '1') {
                this.fancyboxOpenAjaxCommand(command);
            } else {
                this.callCommandWithArgs(command, $('#timeslot-' + command.args.calendar + '-' + command.args.date + '-' + command.args.timeslot), {});
            }
        }
        this.getItems = function($trigger) {
            console.log('override this function with your menu');
        }

        /** Get the selected timeslot elements as array **/
        this.getSelectedTimeslots = function($calendarEntries) {
            //var $timeslot = $(this).parents('.timeslot');
            var $selectedTimeslots = [];
            var $checkedTimeslots = $calendarEntries.find('.timeslot-add:checked');
            var $firstCheckedTimeslot = $checkedTimeslots.filter(':first').parents('.timeslot');
            var $lastCheckedTimeslot = $checkedTimeslots.filter(':last').parents('.timeslot');

            if($firstCheckedTimeslot.length && $lastCheckedTimeslot.length) {
                var startIndex = $firstCheckedTimeslot.data('index');
                var endIndex = $lastCheckedTimeslot.data('index');
                //var index = $timeslot.data('index');

                for(var i = startIndex; i <= endIndex; i++) {
                    var $selectedTimeslot = $calendarEntries.find('.timeslot[data-index="' + i + '"] .timeslot-add').parents('.timeslot');

                    if(!$selectedTimeslot.length) {
                        break;
                    }
                    $selectedTimeslots.push($selectedTimeslot);
                }
            }

            return $selectedTimeslots;
        }

        /** Get the selected timeslot uids as array -> for ajax submission **/
        this.getSelectedTimeslotUids = function($calendarEntries) {
            var $selectedTimeslots = self.getSelectedTimeslots($calendarEntries);
            var selectedTimeslotUids = [];

            for(var i = 0; i < $selectedTimeslots.length; i++) {
                selectedTimeslotUids.push($selectedTimeslots[i].find('.timeslot-add').val());
            }

            return selectedTimeslotUids;
        }

        /** Handle timeslot selection and show multibooking button **/
        this.selectTimeslot = function(event) {
            //var $timeslot = $(this).parents('.timeslot');
            var $selectedTimeslots = self.getSelectedTimeslots($(this).parents('.calendar-entries'));

            $('.tx-ig-reservations .multibooking-button').removeClass('show');
            $('.tx-ig-reservations .timeslot-add').prop('checked', false);

            if($selectedTimeslots.length) {
                //var $firstCheckedTimeslot = $selectedTimeslots[0];
                var $lastCheckedTimeslot = $selectedTimeslots[$selectedTimeslots.length - 1];

                for(var i = 0; i < $selectedTimeslots.length; i++) {
                    $selectedTimeslots[i].find('.timeslot-add').prop('checked', true);
                }

                $lastCheckedTimeslot.find('.multibooking-button').addClass('show');
            }
        }
    }

    $('#dateSelect').on('change', function() {
        $(this).parent('form').submit();
    });

    $('#calendarSelect').on('change', function(e) {
        window.location.href = $(this).val();
    });

    window.igCalendar = new igCalendar();
    $.contextMenu(window.igCalendar.contextMenuConfig);
    $('.tx-ig-reservations-ajax-command').on('click', window.igCalendar.ajaxCommand);

    $(document).on('click', '.tx-ig-reservations .timeslot-add', window.igCalendar.selectTimeslot);

    // Smartphone week/month view
    $('.calendar-col').on('click', '.calendar-header', function() {
	$(this).parent().toggleClass('active');
    });

    /*
    var now = new Date();
    var inAYear = new Date();
    inAYear.setDate(inAYear.getDate() + 365);
    $( "#searchDate" ).pickadate({
        format: 'dd.mm.yyyy',
        formatSubmit: 'yyyy-mm-dd',
        hiddenName: true,
        min: now,
        max: inAYear,
        clear: null,
        today: null
        //,disable: [6,7]
});
    */
    /*
    $( "#searchDate" ).on('change', function() {
        $(this).parents('form').submit();
    });
*/


}));

if($('.calendar-search').length) {
    $('.calendar-search select').on('change', function() {
        window.fullCalendar.refetchEvents();
        //$(this).parents('form').trigger('submit');
    });
}
window.validateReservationForm = function(form) {
    var hasValidationError = false;
    // checkboxes: at least one must been selected
    // checkboxes are marked with class 'js-check-min-1'
    var checkboxes = document.querySelectorAll('.js-check-min-1');
    var checkboxesGroupedByName = {};

    /*
    const messages = {
	selectOneOption: 'Please select at least one option'
    };
    */
    const messages = {
	selectOneOption: 'Bitte wählen Sie mindestens eine Option aus'
    };
    
    checkboxes.forEach(function(checkbox) {
        var name = checkbox.name;
        if (!checkboxesGroupedByName[name]) {
            checkboxesGroupedByName[name] = [];
        }
        checkboxesGroupedByName[name].push(checkbox);

        // Add event listener to clear custom validity on click
        checkbox.addEventListener('click', function() {
            checkboxesGroupedByName[name].forEach(function(cb) {
                cb.setCustomValidity('');
            });
        });
    });
    Object.values(checkboxesGroupedByName).forEach(function(checkboxesInGroup) {
        var checked = checkboxesInGroup.some(function(checkbox) {
            return checkbox.checked;
        });
        if (!checked) {
            checkboxesInGroup[0].setCustomValidity(messages.selectOneOption);
	    hasValidationError = true;
	}
    });
    if (hasValidationError) {
	form.reportValidity();
    }
    // no errors
    return !hasValidationError;
}
