$(function () {
    'use strict';
    window.utils = window.utils || {};
    $.extend(window.utils, {
        fullCalendar: {
            fromExceptionEvent: function (startDate) {
                return {
                    title: '예외',
                    start: startDate,
                    backgroundColor: 'rgb(220,10,10)',
                    isException: true
                };
            },
            generateScheduleEvents: function (currentDate, startDate, scheduleId, scheduleName, cycleType, cycleSize, cycleUnit, holidayType, holidays, exceptionDays) {
                startDate = startDate instanceof Date ? moment(startDate) : startDate;
                if (cycleType === $Code.CycleType.Anytime) {
                    return [
                        {
                            scheduleId: scheduleId,
                            title: scheduleName,
                            start: $G.date(startDate)

                        }
                    ];
                }
                currentDate = currentDate instanceof Date ? moment(currentDate) : currentDate;

                var events = [];
                var cycle;
                var unit = $Code.CycleUnit;
                var htype = $Code.HolidayWorkType;
                var term = 1;
                switch (cycleUnit) {
                    case unit.Daily: cycle = 'days'; break;
                    case unit.Weekly: cycle = 'weeks'; break;
                    case unit.Monthly: cycle = 'months'; break;
                    case unit.Quaterly: cycle = 'months'; term = 3; break;
                    case unit.HalfYearly: cycle = 'months'; term = 6; break;
                    case unit.Yearly: cycle = 'years'; break;
                }
                if (currentDate.year() < startDate.year()) return events;
                if (currentDate.year() === startDate.year() && currentDate.month() < startDate.month()) return events;
                var date = startDate.clone();
                if (currentDate.month() !== startDate.month()) {
                    date.startOf('days');
                    while (date.year() < currentDate.year() || date.month() < currentDate.month()) {
                        date.add(cycleSize * term, cycle);
                    }
                }
                var m = date.month();
                var formattedDate;
                var willPush = false;

                if (holidayType === htype.NextDayWork) {

                    var isPendingWork = false;
                    var nextDay = date.clone();
                    var formattedNextDate = $G.date(nextDay);

                    for (; date.month() === m ; date.add(1, 'days')) {

                        formattedDate = $G.date(date);
                        if (formattedNextDate === formattedDate) {

                            nextDay.add(cycleSize * term, cycle);
                            formattedNextDate = $G.date(nextDay);

                            if (holidays.indexOf(formattedDate) >= 0) {
                                isPendingWork = true;
                                continue;
                            }
                            if (exceptionDays.indexOf(formattedDate) >= 0) {
                                isPendingWork = false;
                                events.push(this.fromExceptionEvent(formattedDate));
                                continue;
                            }
                            events.push({
                                title: scheduleName,
                                start: formattedDate
                            });
                            isPendingWork = false;
                        }
                        else if (isPendingWork) {
                            if (holidays.indexOf(formattedDate) >= 0) {
                                continue;
                            }
                            if (exceptionDays.indexOf(formattedDate) >= 0) {
                                isPendingWork = false;
                                events.push(this.fromExceptionEvent(formattedDate));
                                continue;
                            }
                            events.push({
                                scheduleId: scheduleId,
                                title: scheduleName,
                                start: formattedDate
                            });
                            isPendingWork = false;
                        }
                    }
                }
                else {
                    for (; date.month() === m ; date.add(cycleSize * term, cycle)) {
                        formattedDate = $G.date(date);
                        if (holidays.indexOf(formattedDate) >= 0) {
                            willPush = true;
                            switch (holidayType) {
                                case htype.Work: break; // Nothing to do
                                case htype.NotWork:
                                    {
                                        willPush = false;
                                        break;
                                    } // Nothing to do
                            }
                            if (willPush === false) continue;
                        }
                        events.push({
                            scheduleId: scheduleId,
                            title: scheduleName,
                            start: formattedDate
                        });
                    }

                }
                return events;
            },
            create: function (id, options) {

                var events = options.events || [];
                var self = $('#' + id);
                options = $.extend({}, options, {
                    header: {
                        right: 'prev,next today',
                        left: 'title'
                    },
                    lang: 'ko',
                    buttonIcons: false,
                    weekNumbers: true,
                    selectable: true,
                    selectHelper: true,
                    events: events
                });
                if (options.selectable === undefined) {
                    options.selectable = true;
                }
                self.fullCalendar(options);

                return {
                    self: self,
                    events: events,
                    updateEvents: function (newEvents) {
                        self.fullCalendar('removeEventSource', events);
                        if (newEvents !== undefined) {
                            events = newEvents;
                        }
                        self.fullCalendar('addEventSource', events);
                    },
                    setReadOnly: function (isReadOnly) {
                        //                        console.log( self.fullCalendar( 'option', 'selectable' ) );
                        var view = self.fullCalendar('getView');
                        view.calendar.options['selectable'] = isReadOnly ? false : true;
                        //                        if( isReadOnly ) {

                        ////                            console.log( 'after setting false ' + self.fullCalendar( 'option', 'selectable' ) );
                        //                        }
                        //                        else {
                        //                            self.fullCalendar( { 'selectable': true } );
                        //                        }
                    },
                    isExistEvent: function (day, handle, title) {
                        var isExist = false;
                        if (arguments.length === 3) {
                            $.each(events, function (i, event) {
                                if ($G.date(event.start) === $G.date(day) && event.title == title) {
                                    if (typeof handle === 'function') handle(i, event);
                                    isExist = true;
                                    return false;
                                }
                            });
                        }
                        else {
                            $.each(events, function (i, event) {
                                if ($G.date(event.start) === $G.date(day)) {
                                    if (typeof handle === 'function') handle(i, event);
                                    isExist = true;
                                    return false;
                                }
                            });
                        }
                        return isExist;
                    },

                    pushEventIfNotExist: function (title, day, isRefresh) {
                        if (this.isExistEvent(day, null, title) == false) {
                            this.pushEvent(title, day, isRefresh);
                        }
                    },
                    pushEventInArray: function (destArray, title, day) {
                        var o = {
                            title: title,
                            start: day,
                            allDay: true,
                        };
                        destArray.push(o);
                        return o;
                    },
                    pushEvent: function (title, day, isRefresh) {
                        this.pushEventInArray(events, title, day);
                        if (isRefresh !== undefined && isRefresh) this.updateEvents();
                    },
                    pushExceptionEvent: function (day, isRefresh) {
                        var o = this.pushEventInArray(events, '예외', day);
                        o.isException = true;
                        o.backgroundColor = 'rgb(210,10,10)';
                        if (isRefresh !== undefined && isRefresh) this.updateEvents();
                    },
                    clearEvents: function (isRefresh) {
                        events.splice(0, events.length);
                        if (isRefresh !== undefined && isRefresh) this.updateEvents();
                    },
                    removeEvent: function (day, title, isRefresh) {
                        var wasDeleted = false;
                        if (title === undefined) {
                            this.isExistEvent(day, function (i) {
                                events.splice(i, 1);
                                wasDeleted = true;
                            });
                        }
                        else {
                            this.isExistEvent(day, function (i) {
                                events.splice(i, 1);
                                wasDeleted = true;
                            }, title);
                        }

                        if (arguments.length == 3 && isRefresh && wasDeleted) {
                            console.log('updateEvents in remove');
                            this.updateEvents();
                        }

                        return wasDeleted;
                    },
                    getDate: function () {
                        return self.fullCalendar('getDate');
                    },
                    getEvents: function (date, callback) {
                        $.each(events, function (i, event) {
                            if (event.start === date) {
                                callback(event);
                            }
                        });
                    }
                };
            }
        }
    });
});