function parseISO86012000(s) {
    //var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/);
    var m = s.match(/^([0-9]{4})(([0-9]{2})(([0-9]{2})([T]([0-9]{2})([0-9]{2})(([0-9]{2})(\.([0-9]+))?)?(Z)?)?)?)?$/);
    
    if (!m) {
        return null;
    }
    var date = new Date(m[1], 0, 1);
    date.setUTCFullYear(
        m[1],
        m[3] ? m[3] - 1 : 0,
        m[5] || 1
    );
    date.setUTCHours(
        m[7] || 0,
        m[8] || 0,
        m[10] || 0,
        m[12] ? Number("0." + m[12]) * 1000 : 0
    );
    if (m[14]) {
        var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0);
        offset *= m[15] == '-' ? 1 : -1;
        date = new Date(+date + (offset * 60 * 1000));
    }
    return date;
}

function reservation_form_check_vehicle_type() {
    var selected_vehicle_type = $field_input_reservation_form_vehicle_type.val();
    if (selected_vehicle_type.length > 0) {
        $('#formfield_reservation_form_vehicle_brand, #formfield_reservation_form_vehicle_model, #formfield_reservation_form_vehicle_type_approval').show();
    } else {
        $('#formfield_reservation_form_vehicle_brand, #formfield_reservation_form_vehicle_model, #formfield_reservation_form_vehicle_type_approval').hide();
    }
    $formfield_reservation_form_services.each(function() {
        var vehicle_types = $(this).data('vehicle_types');
        if (vehicle_types.length == 0 || $.inArray(selected_vehicle_type, vehicle_types) >= 0) {
            $(this).show();
        } else {
            $('input', $(this)).removeAttr('checked');
            $(this).hide();
        }
    });
    reservation_form_check_services();
}

function reservation_form_check_services() {
    // get total duration of selected services
    total_duration = 0;
    $('input:checked', $formfield_reservation_form_services).each(function() {
        total_duration += $(this).data('duration');
    });
    total_duration = Math.ceil((total_duration/15)) * 15;
    
    // destroy a maybe existing fullCalendar
    $fcContainer.fullCalendar('destroy');

    // if services are selected
    if (total_duration > 0) {
        $('#formfield_reservation_form_appointment_select_services_info').hide();
        
        var business_hours = $reservation_form.data('business_hours'); // default business hours
        var business_hours_exceptions = $reservation_form.data('business_hours_exceptions'); // default business hours
        var calendar_offset = $reservation_form.data('calendar_offset'); // offset in days, used to get the first available date for which we make reservations
        var caldav_freebusy_url = $reservation_form.data('caldav_freebusy_url'); // the url from where we get freebusy information
        
        // min and max time of the calendar display
        var minTime = null;
        var maxTime = null;
        $.each(business_hours, function(index, day) {
            var tstartHour = parseInt(day['tstart'].split(':')[0]);
            var tendHour = parseInt(day['tend'].split(':')[0]);
            if (!minTime || minTime > tstartHour) {
                minTime = tstartHour;
            }
            if (!maxTime || maxTime < tendHour) {
                maxTime = tendHour;
            }
        });
        maxTime = maxTime + 1;
        
        // fill an array of hours for each workday
        var businessHours = {}
        $.each([1, 2, 3, 4, 5], function(index, value) {
            businessHours[value] = {}
            for (hour=0; hour<=23; hour++) {
                businessHours[value][hour] = {0: true, 15: true, 30: true, 45: true};
            }
        });
        $.each(business_hours, function(index, value) {
            var currentWeekday = parseInt(value.weekday) + 1;
            var currentStart = value.tstart.split(':');
            var currentStartHour = parseInt(currentStart[0]);
            var currentStartMinute = parseInt(currentStart[1]);
            var currentEnd = value.tend.split(':');
            var currentEndHour = parseInt(currentEnd[0]);
            var currentEndMinute = parseInt(currentEnd[1]);
            for (hour=currentStartHour; hour<=currentEndHour; hour++) {
                if (hour == currentStartHour) {
                    $.each([0, 15, 30, 45], function(mIndex, mValue) {
                        if (mValue >= currentStartMinute) {
                            businessHours[currentWeekday][hour][mValue] = false;
                        }
                    });
                } else if (hour == currentEndHour) {
                    $.each([0, 15, 30, 45], function(mIndex, mValue) {
                        if (mValue < currentEndMinute) {
                            businessHours[currentWeekday][hour][mValue] = false;
                        }
                    });
                } else {
                    businessHours[currentWeekday][hour] = {0: false, 15: false, 30: false, 45: false};
                }
            }
        });
        
        // fill an array of business hours exceptions
        var businessHoursExceptions = {}
        $.each(business_hours_exceptions, function(index, value) {
            var currentDate = new Date(value.date);
            currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate());
            
            var currentYear = currentDate.getFullYear();
            var currentMonth = currentDate.getMonth();
            var currentDay = currentDate.getDate();
            
            if (!businessHoursExceptions[currentYear]) {
                businessHoursExceptions[currentYear] = {};
            }
            if (!businessHoursExceptions[currentYear][currentMonth]) {
                businessHoursExceptions[currentYear][currentMonth] = {};
            }
            if (!businessHoursExceptions[currentYear][currentMonth][currentDay]) {
                businessHoursExceptions[currentYear][currentMonth][currentDay] = {};
                for (hour=0; hour<=23; hour++) {
                    businessHoursExceptions[currentYear][currentMonth][currentDay][hour] = {0: true, 15: true, 30: true, 45: true};
                }
            }
            if (value.tstart.length > 0 && value.tend.length > 0) {
                var currentStart = value.tstart.split(':');
                var currentStartHour = parseInt(currentStart[0]);
                var currentStartMinute = parseInt(currentStart[1]);
                var currentEnd = value.tend.split(':');
                var currentEndHour = parseInt(currentEnd[0]);
                var currentEndMinute = parseInt(currentEnd[1]);
                for (hour=currentStartHour; hour<=currentEndHour; hour++) {
                    if (hour == currentStartHour) {
                        $.each([0, 15, 30, 45], function(mIndex, mValue) {
                            if (mValue >= currentStartMinute) {
                                businessHoursExceptions[currentYear][currentMonth][currentDay][hour][mValue] = false;
                            }
                        });
                    } else if (hour == currentEndHour) {
                        $.each([0, 15, 30, 45], function(mIndex, mValue) {
                            if (mValue < currentEndMinute) {
                                businessHoursExceptions[currentYear][currentMonth][currentDay][hour][mValue] = false;
                            }
                        });
                    } else {
                        businessHoursExceptions[currentYear][currentMonth][currentDay][hour] = {0: false, 15: false, 30: false, 45: false};
                    }
                }
            }
        });
        
        // get the first available date for which we can make reservations
        // make sure we set the startday for the calendar to a monday
        var firstAvailDate = new Date();
        firstAvailDate = new Date(firstAvailDate.setDate(firstAvailDate.getDate() + calendar_offset));
        var firstAvailYear = firstAvailDate.getFullYear();
        var firstAvailMonth = firstAvailDate.getMonth();
        var firstAvailDay = firstAvailDate.getDate();
        firstAvailDate = new Date(firstAvailYear, firstAvailMonth, firstAvailDay);
        
        startDate = new Date(firstAvailDate);
        if (startDate.getDay() == 0) {
            startDate = new Date(startDate.setDate(startDate.getDate() + 1));
        } else if (startDate.getDay() == 6) {
            startDate = new Date(startDate.setDate(startDate.getDate() + 2));
        } else {
            startDate = new Date(startDate.setDate(startDate.getDate() - (startDate.getDay() - 1)))
        }        
        
        var appointment_val = $field_input_reservation_form_appointment_appointment.val();
        var existing_events = null;
        if (appointment_val.length > 0) {
            var appointment_events = appointment_val.split(';');
            var appointment_duration = 0;
            try {
                existing_events = [];
                $.each(appointment_events, function(index, appointment_event) {
                    var parts = appointment_event.split('/');
                    var start = parseISO86012000(parts[0]);
                    var end = parseISO86012000(parts[1]);
                    var event = {
                        id: 'fc-userevent',
                        title: 'belegt',
                        start: new Date(start),
                        end: new Date(end),
                        allDay: false,
                        className: 'fc-userevent'
                    }
                    existing_events.push($.extend(true, {}, event));
                });
                appointmentStartDate = existing_events[0]['start']
                if (appointmentStartDate >= firstAvailDate) {
                    $.each(existing_events, function(index, existing_event) {
                        existing_event['displaytime'] = $.fullCalendar.formatDate(existing_events[0].start, 'HH:mm') + ' - ' + $.fullCalendar.formatDate(existing_events[existing_events.length - 1].end, 'HH:mm');
                    });
                    startDate = new Date(appointmentStartDate.getFullYear(), appointmentStartDate.getMonth(), appointmentStartDate.getDate());
                    if (startDate.getDay() == 0) {
                        startDate = new Date(startDate.setDate(startDate.getDate() + 1));
                    } else if (startDate.getDay() == 6) {
                        startDate = new Date(startDate.setDate(startDate.getDate() + 2));
                    } else {
                        startDate = new Date(startDate.setDate(startDate.getDate() - (startDate.getDay() - 1)))
                    }
                } else {
                    existing_events = null;
                }
            } catch(e) {
                $field_input_reservation_form_appointment_appointment.empty();
            }
        }
        
        var startYear = startDate.getFullYear();
        var startMonth = startDate.getMonth();
        var startDay = startDate.getDate();
        
        // init fullCalendar
        $fcContainer.fullCalendar({
            firstDay: 1,
            defaultView: 'agendaWeek',
            weekends: false,
            allDaySlot: false,
            slotMinutes: 15,
            titleFormat: {
                week: 'dd.[ MMMM][ yyyy]{ - dd. MMMM yyyy}'
            },
            //aspectRatio: 1,
            contentHeight: 700,
            axisFormat: 'HH:mm', //rows - time
            columnFormat: {
                week: 'ddd dd.MM' //columns - day
            },
            timeFormat: 'HH:mm', //events
            
            year: startYear,
            month: startMonth,
            date: startDay,
            minTime: minTime,
            maxTime: maxTime,
            
            monthNames: $.datepicker._defaults['monthNames'],
            monthNamesShort: $.datepicker._defaults['monthNamesShort'],
            dayNames: $.datepicker._defaults['dayNames'],
            dayNamesShort: $.datepicker._defaults['dayNamesShort'],
            
            buttonText: {
                today: ''
            },
            
            selectHelper: true,

            // every time a view gets loaded
            viewDisplay: function(view) {                
                var container = this;
                var $container = $(container);
                var calendar = $(container).data('fullCalendar');
                var colCnt = view.getColCnt();
                var colWidth = view.getColWidth();
                var dayTable = $('.fc-agenda-days', $container);
                var slotTable = $('.fc-agenda-slots', $container);
                var dayHead = dayTable.find('thead');
                var axisFirstCells = dayHead.find('th:first');
                axisFirstCells = axisFirstCells.add(slotTable.find('th:first'));
                var axisWidth = 0;
                axisFirstCells.each(function(i, _cell) {
                    axisWidth = Math.max(axisWidth, $(_cell).outerWidth());
                });
                // when moving the mouse over hour slots display a selection with the total amount of time for the previous selected services
                $('.fc-agenda-slots td', $container).bind('mousemove', {container: container, $container: $container, calendar: calendar, view: view, colCnt: colCnt, colWidth: colWidth, dayTable: dayTable, slotTable: slotTable, dayHead: dayHead, axisFirstCells: axisFirstCells, axisWidth: axisWidth}, function(event) {
                    var weekDates = $container.data('weekDates');
                    var col = Math.min(colCnt-1, Math.floor((event.pageX - dayTable.offset().left - axisWidth) / colWidth));
                    var selectStartDate = $.fullCalendar.addDays($.fullCalendar.cloneDate(view.visStart), col);
                    if (selectStartDate < firstAvailDate) {
                        return;
                    }
                    var rowMatch = this.parentNode.className.match(/fc-slot(\d+)/);
                    var mins = parseInt(rowMatch[1]) * view.opt('slotMinutes');
                    var hours = Math.floor(mins/60);
                    selectStartDate.setHours(hours);
                    selectStartDate.setMinutes(mins%60 + view.getMinMinute());
                    var selectStartYear = selectStartDate.getFullYear();
                    var selectStartMonth = selectStartDate.getMonth();
                    var selectStartDay = selectStartDate.getDate();
                    var selectStartHour = selectStartDate.getHours();
                    var selectStartMinute = selectStartDate.getMinutes();
                    
                    var selectEndDate = new Date(selectStartDate);
                    
                    var tdSlots = total_duration/15;
                    var current_tdSlot = 1;
                    while (true) {
                        selectEndDate.setMinutes(selectEndDate.getMinutes() + 15);
                        if (selectEndDate.getDate() != selectStartDay || selectEndDate.getHours() > maxTime) {
                            break;
                        }
                        if (weekDates[selectStartYear][selectStartMonth][selectStartDay][selectEndDate.getHours()][selectEndDate.getMinutes()] == true) {
                            if (current_tdSlot == tdSlots) {
                                break;
                            }
                            continue;
                        }
                        current_tdSlot++;
                        if (current_tdSlot > tdSlots) {
                            break;
                        }
                    }
                    if (current_tdSlot < tdSlots) {
                        while (true) {
                            selectStartDate.setMinutes(selectStartDate.getMinutes() - (tdSlots - current_tdSlot) * 15);
                            selectEndDate = new Date(selectStartDate);
                            selectEndDate.setMinutes(selectEndDate.getMinutes() + total_duration);
                            break;
                        }
                    }
                    
                    calendar.select(selectStartDate, selectEndDate, false);
                    $('.fc-select-helper .fc-event-time', container).html(calendar.formatDate(selectStartDate, 'HH:mm') + ' - ' + calendar.formatDate(selectEndDate, 'HH:mm'));
                });
                $('.fc-agenda-slots td', $container).bind('mouseleave', {calendar: calendar}, function(event) {
                    calendar.unselect();
                });
            },
            dayClick: function(date, allDay, jsEvent, view) {
                if (date < firstAvailDate) {
                    return;
                }
                var weekDates = $fcContainer.data('weekDates');
                var calendar = $fcContainer.data('fullCalendar');
                
                var dateYear = date.getFullYear();
                var dateMonth = date.getMonth();
                var dateDay = date.getDate();
                
                var eventStartDate = new Date(date);
                var eventEndDate = new Date(eventStartDate);
                
                var events = [];
                var event = {
                    id: 'fc-userevent',
                    title: 'belegt',
                    start: new Date(eventStartDate),
                    allDay: false,
                    className: 'fc-userevent'
                }
                
                var tdSlots = total_duration/15;
                var current_tdSlot = 1;
                while (true) {
                    eventEndDate.setMinutes(eventEndDate.getMinutes() + 15);
                    if (eventEndDate.getDate() != dateDay || eventEndDate.getHours() > maxTime) {
                        events = [];
                        break;
                    }
                    if (weekDates[dateYear][dateMonth][dateDay][eventEndDate.getHours()][eventEndDate.getMinutes()] == true) {
                        if (event != null) {
                            event['end'] = new Date(eventEndDate);
                            events.push($.extend(true, {}, event));
                            event = null;
                        }
                        eventStartDate = new Date(eventEndDate);
                        eventStartDate.setMinutes(eventStartDate.getMinutes() + 15);
                        continue;
                    }
                    current_tdSlot++;
                    if (current_tdSlot > tdSlots) {
                        if (event != null) {
                            event['end'] = new Date(eventEndDate);
                            events.push($.extend(true, {}, event));
                            event = null;
                        }
                        break;
                    } else {
                        if (event == null) {
                            event = {
                                id: 'fc-userevent',
                                title: 'belegt',
                                start: new Date(eventStartDate),
                                allDay: false,
                                className: 'fc-userevent'
                            }
                        }
                    }
                }
                if (events.length == 0) {
                    while (true) {
                        eventStartDate = new Date(date);
                        eventStartDate.setMinutes(eventStartDate.getMinutes() - (tdSlots - current_tdSlot) * 15);
                        eventEndDate = new Date(eventStartDate);
                        eventEndDate.setMinutes(eventEndDate.getMinutes() + total_duration);
                        event = {
                            id: 'fc-userevent',
                            title: 'belegt',
                            start: new Date(eventStartDate),
                            end: new Date(eventEndDate),
                            allDay: false,
                            className: 'fc-userevent'
                        }
                        events.push($.extend(true, {}, event));
                        break;
                    }
                }
                
                calendar.removeEvents('fc-userevent');
                calendar.unselect();
                input_values = []
                $.each(events, function(index, event) {
                    event['displaytime'] = calendar.formatDate(events[0].start, 'HH:mm') + ' - ' + calendar.formatDate(events[events.length - 1].end, 'HH:mm');
                    calendar.renderEvent(event, true);
                    input_values.push($.icalendar.formatDateTime(event['start']) + '/' + $.icalendar.formatDateTime(event['end']));
                });
                $field_input_reservation_form_appointment_appointment.val(input_values.join(';'));
            },
            
            // the event source
            // get the freebusy events and merge it with the opening hours and opening hours exceptions to a an events array, so we dont see single events on the calendar, but continuous free blocks
            events: function(start, end, callback) {
                calendar = $fcContainer.data('fullCalendar');
                $.ajax({
                    url: caldav_freebusy_url,
                    dataType: 'text',
                    data: {
                        'start': calendar.formatDate(start, 'yyyy-MM-dd'),
                        'end': calendar.formatDate(end, 'yyyy-MM-dd')
                    },
                    success: function(doc) {
                        calendar = $fcContainer.data('fullCalendar');
                        var ics = $.icalendar.parse(doc);
                        var ics_freebusy = [];
                        if (ics.vfreebusy && ics.vfreebusy.freebusy) {
                            if ($.isArray(ics.vfreebusy.freebusy)) {
                                ics_freebusy = ics.vfreebusy.freebusy;
                            } else {
                                ics_freebusy.push(ics.vfreebusy.freebusy);
                            }
                        }
                        
                        var firstWeekDate = $fcContainer.fullCalendar('getDate');
                        var firstWeekYear = firstWeekDate.getFullYear();
                        var firstWeekMonth = firstWeekDate.getMonth();
                        var firstWeekDay = firstWeekDate.getDate();
                        firstWeekDate = new Date(firstWeekYear, firstWeekMonth, firstWeekDay);
                        
                        var lastWeekDate = new Date(firstWeekDate.getFullYear(), firstWeekDate.getMonth(), firstWeekDate.getDate() + 4);
                        var lastWeekYear = lastWeekDate.getFullYear();
                        var lastWeekMonth = lastWeekDate.getMonth();
                        var lastWeekDay = lastWeekDate.getDate();
                        var lastWeekDateMS = lastWeekDate.getTime();
                        
                        // weekDates is a dictionary of 15min slots and the information if the slot is free or busy ... true is busy
                        weekDates = {};
                        for (day=0;day<=4;day++) {
                            currentDate = new Date(firstWeekDate);
                            currentDate.setDate(firstWeekDate.getDate() + day);
                            currentYear = currentDate.getFullYear();
                            currentMonth = currentDate.getMonth();
                            currentDay = currentDate.getDate();
                            currentWeekday = currentDate.getDay();
                            
                            if (!weekDates[currentYear]) {
                                weekDates[currentYear] = {};
                            }
                            if (!weekDates[currentYear][currentMonth]) {
                                weekDates[currentYear][currentMonth] = {};
                            }
                            if (currentDate < firstAvailDate) {
                                weekDates[currentYear][currentMonth][currentDay] = {};
                                for (hour=0; hour<=23; hour++) {
                                    weekDates[currentYear][currentMonth][currentDay][hour] = {0: true, 15: true, 30: true, 45: true};
                                }
                            } else if (businessHoursExceptions[currentYear] && businessHoursExceptions[currentYear][currentMonth] && businessHoursExceptions[currentYear][currentMonth][currentDay]) {
                                weekDates[currentYear][currentMonth][currentDay] = $.extend(true, {}, businessHoursExceptions[currentYear][currentMonth][currentDay]);
                            } else {
                                weekDates[currentYear][currentMonth][currentDay] = $.extend(true, {}, businessHours[currentWeekday]);
                            }
                        }
                        
                        $.each(ics_freebusy, function(index, value) {
                            icsStartDate = new Date(value.start);
                            icsStartYear = icsStartDate.getFullYear();
                            icsStartMonth = icsStartDate.getMonth();
                            icsStartDay = icsStartDate.getDate();
                            icsStartHour = icsStartDate.getHours();
                            icsStartMinute = icsStartDate.getMinutes();
                            icsStartDateOnly = new Date(icsStartYear, icsStartMonth, icsStartDay);
                            icsStartDateOnlyMS = icsStartDateOnly.getTime();
                            if (icsStartDate >= firstAvailDate && icsStartDate >= firstWeekDate && icsStartDate < new Date(lastWeekYear, lastWeekMonth, lastWeekDay + 1)) {
                                icsEndDate = new Date(value.end);
                                icsEndYear = icsEndDate.getFullYear();
                                icsEndMonth = icsEndDate.getMonth();
                                icsEndDay = icsEndDate.getDate();
                                icsEndHour = icsEndDate.getHours();
                                icsEndMinute = icsEndDate.getMinutes();
                                icsEndDateOnly = new Date(icsEndYear, icsEndMonth, icsEndDay);
                                icsEndDateOnlyMS = icsEndDateOnly.getTime();
                                
                                if (icsStartDateOnlyMS  == icsEndDateOnlyMS) {
                                    for (hour=icsStartHour; hour<=icsEndHour; hour++) {
                                        if (hour == icsStartHour) {
                                            $.each([0, 15, 30, 45], function(mIndex, mValue) {
                                                if (mValue >= icsStartMinute) {
                                                    weekDates[icsStartYear][icsStartMonth][icsStartDay][hour][mValue] = true;
                                                }
                                            });
                                        } else if (hour == icsEndHour) {
                                            $.each([0, 15, 30, 45], function(mIndex, mValue) {
                                                if (mValue < icsEndMinute) {
                                                    weekDates[icsStartYear][icsStartMonth][icsStartDay][hour][mValue] = true;
                                                }
                                            });
                                        } else {
                                            weekDates[icsStartYear][icsStartMonth][icsStartDay][hour] = {0: true, 15: true, 30: true, 45: true};
                                        }
                                    }
                                } else {
                                    icsCurrentDate = new Date(icsStartDateOnly);
                                    icsCurrentYear = icsCurrentDate.getFullYear();
                                    icsCurrentMonth = icsCurrentDate.getMonth();
                                    icsCurrentDay = icsCurrentDate.getDate();
                                    icsCurrentDateMS = icsCurrentDate.getTime();
                                    while (icsCurrentDateMS <= icsEndDateOnlyMS && icsCurrentDateMS <= lastWeekDateMS) {
                                        if (icsCurrentDateMS == icsStartDateOnlyMS) {
                                            for (hour=icsStartHour; hour<=maxTime; hour++) {
                                                if (hour == icsStartHour) {
                                                    $.each([0, 15, 30, 45], function(mIndex, mValue) {
                                                        if (mValue >= icsStartMinute) {
                                                            weekDates[icsCurrentYear][icsCurrentMonth][icsCurrentDay][hour][mValue] = true;
                                                        }
                                                    });
                                                } else {
                                                    weekDates[icsCurrentYear][icsCurrentMonth][icsCurrentDay][hour] = {0: true, 15: true, 30: true, 45: true};
                                                }
                                            }
                                        } else if (icsCurrentDateMS == icsEndDateOnlyMS) {
                                            for (hour=minTime; hour<=icsEndHour; hour++) {
                                                if (hour == icsEndHour) {
                                                    $.each([0, 15, 30, 45], function(mIndex, mValue) {
                                                        if (mValue < icsEndMinute) {
                                                            weekDates[icsCurrentYear][icsCurrentMonth][icsCurrentDay][hour][mValue] = true;
                                                        }
                                                    });
                                                } else {
                                                    weekDates[icsCurrentYear][icsCurrentMonth][icsCurrentDay][hour] = {0: true, 15: true, 30: true, 45: true};
                                                }
                                            }
                                        } else {
                                            for (hour=minTime; hour<=maxTime; hour++) {
                                                weekDates[icsCurrentYear][icsCurrentMonth][icsCurrentDay][hour] = {0: true, 15: true, 30: true, 45: true};
                                            }
                                        }
                                        
                                        icsCurrentDate.setDate(icsCurrentDay + 1);
                                        icsCurrentYear = icsCurrentDate.getFullYear();
                                        icsCurrentMonth = icsCurrentDate.getMonth();
                                        icsCurrentDay = icsCurrentDate.getDate();
                                        icsCurrentDateMS = icsCurrentDate.getTime();
                                        break;
                                    }
                                }
                            }
                        });
                        $fcContainer.data('weekDates', $.extend(true, {}, weekDates));
                        
                        // make continuous event blocks
                        var events = [];
                        $.each(weekDates, function(year, months) {
                            $.each(months, function(month, days) {
                                $.each(days, function(day, hours) {
                                    var currentEventStart = null;
                                    var currentEventEnd = null;
                                    $.each(hours, function(hour, minutes) {
                                        $.each(minutes, function(minute, value) {
                                            if (value == true && currentEventStart == null) {
                                                currentEventStart = new Date(year, month, day, hour, minute);
                                            }
                                            if (value == false && currentEventStart != null) {
                                                currentEventEnd = new Date(year, month, day, hour, minute);
                                            }
                                            if (currentEventStart != null && currentEventEnd != null) {
                                                events.push({
                                                    title: 'belegt',
                                                    start: new Date(currentEventStart),
                                                    end: new Date(currentEventEnd),
                                                    allDay: false
                                                });
                                                currentEventStart = null;
                                                currentEventEnd = null;
                                            }
                                        });
                                    });
                                    if (currentEventStart != null && currentEventEnd == null) {
                                        events.push({
                                            title: 'belegt',
                                            start: new Date(currentEventStart),
                                            end: new Date(year, month, day, maxTime),
                                            allDay: false
                                        });
                                        currentEventStart = null;
                                        currentEventEnd = null;
                                    }
                                });
                            });
                        });
                        
                        callback(events);
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        alert(textStatus);
                    }
               });
            },
            
            eventAfterRender: function( event, element, view ) {
                if (event['displaytime']) {
                    $('.fc-event-time', element).html(event['displaytime']);
                }
            }
        });
        if (existing_events) {
            $.each(existing_events, function(index, event) {
                calendar.renderEvent(event, true);
            });
        }
    } else {
        $('#formfield_reservation_form_appointment_select_services_info').show();
        $field_input_reservation_form_appointment_appointment.empty();
    }
}

$(function() {
    $('body').delegate('#field_input_reservation_form_vehicle_type', 'change', function() {
        $field_input_reservation_form_appointment_appointment.empty();
        reservation_form_check_vehicle_type();
    });

    $('body').delegate('#formcheckboxlist_reservation_form_services .formfield_services input', 'change', function() {
        $field_input_reservation_form_appointment_appointment.empty();
        reservation_form_check_services();
    });
    
    $reservation_form = $('form.reservation_form');
    if ($reservation_form.length > 0) {
        // use jquery ui's datepicker to get locale stuff (month-, daynames, etc..)
        $.datepicker.setDefaults($.datepicker.regional[language_codes[lang]['iso-639-1']]);
        
        $reservation_form.data('business_hours', $.parseJSON(decodeURIComponent($reservation_form.data('business_hours')))); // default business hours
        $reservation_form.data('business_hours_exceptions', $.parseJSON(decodeURIComponent($reservation_form.data('business_hours_exceptions')))); // business hours exceptions
        $reservation_form.data('calendar_offset', parseInt($reservation_form.data('calendar_offset'))); // offset in days, used to get the first available date for which we make reservations
        $reservation_form.data('caldav_freebusy_url', $reservation_form.data('caldav_freebusy_url')); // the url from where we get freebusy information
        
        $field_input_reservation_form_vehicle_type = $('#field_input_reservation_form_vehicle_type');
        
        $formfield_reservation_form_services = $('.formfield_services', '#formcheckboxlist_reservation_form_services');
        $formfield_reservation_form_services.each(function() {
            $(this).data('vehicle_types', $.parseJSON(decodeURIComponent($(this).data('vehicle_types'))));
            var duration = $.parseJSON(decodeURIComponent($(this).data('duration')));
            $(this).data('duration', duration);
            $('input', $(this)).data('duration', duration);
        });
        
        $field_input_reservation_form_appointment_appointment = $('#field_input_reservation_form_appointment_appointment');
        
        // add a calendar container to the corresponding fieldset
        $('> .innercontent', '#formfieldset_reservation_form_appointment').append('<div class="calendar"></div>');
        $fcContainer = $('.reservation_form .formfieldset_appointment > .innercontent .calendar');
        reservation_form_check_vehicle_type();
    }
});
