'use strict';

define(
    [
        'jquery',
        'vent',
        'marionette',
        'moment',
        'Calendar/Collection',
        'Shared/UiSettingsModel',
        'Activity/Queue/QueueCollection',
        'Config',
        'Mixins/backbone.signalr.mixin',
        'fullcalendar',
        'jquery.easypiechart'
    ], function ($, vent, Marionette, moment, CalendarCollection, UiSettings, QueueCollection, Config) {

        return Marionette.ItemView.extend({
            storageKey: 'calendar.view',

            initialize: function () {
                this.collection = new CalendarCollection().bindSignalR({ updateOnly: true });
                this.listenTo(this.collection, 'change', this._reloadCalendarEvents);
                this.listenTo(QueueCollection, 'sync', this._reloadCalendarEvents);
            },

            render    : function () {
                this.$el.empty().fullCalendar(this._getOptions());
            },

            onShow: function () {
                this.$('.fc-button-today').click();
            },

            _viewRender: function (view) {

                if ($(window).width() < 768) {
                    this.$('.fc-header-title').show();
                    this.$('.calendar-title').remove();

                    var title = this.$('.fc-header-title').text();
                    var titleDiv = '<div class="calendar-title"><h2>{0}</h2></div>'.format(title);

                    this.$('.fc-header').before(titleDiv);
                    this.$('.fc-header-title').hide();
                }

                if (Config.getValue(this.storageKey) !== view.name) {
                    Config.setValue(this.storageKey, view.name);
                }
                
                this._getEvents(view);
            },
            
            _eventRender: function (event, element) {
                this.$(element).addClass(event.statusLevel);
                this.$(element).children('.fc-event-inner').addClass(event.statusLevel);

                if (event.downloading) {
                    var progress = 100 - (event.downloading.get('sizeleft') / event.downloading.get('size') * 100);
                    var releaseTitle = event.downloading.get('title');
                    var estimatedCompletionTime = moment(event.downloading.get('estimatedCompletionTime')).fromNow();
                    var status = event.downloading.get('status').toLocaleLowerCase();
                    var errorMessage = event.downloading.get('errorMessage');

                    if (status === 'pending') {
                        this._addStatusIcon(element, 'icon-time', 'Release will be processed {0}'.format(estimatedCompletionTime));
                    }

                    else if (errorMessage) {
                        if (status === 'completed') {
                            this._addStatusIcon(element, 'icon-nd-import-failed', 'Import failed: {0}'.format(errorMessage));
                        }
                        else {
                            this._addStatusIcon(element, 'icon-nd-download-failed', 'Download failed: {0}'.format(errorMessage));
                        }
                    }

                    else if (status === 'failed') {
                        this._addStatusIcon(element, 'icon-nd-download-failed', 'Download failed: check download client for more details');
                    }

                    else if (status === 'warning') {
                        this._addStatusIcon(element, 'icon-nd-download-warning', 'Download warning: check download client for more details');
                    }

                    else {
                        this.$(element).find('.fc-event-time')
                            .after('<span class="chart pull-right" data-percent="{0}"></span>'.format(progress));

                        this.$(element).find('.chart').easyPieChart({
                            barColor  : '#ffffff',
                            trackColor: false,
                            scaleColor: false,
                            lineWidth : 2,
                            size      : 14,
                            animate   : false
                        });

                        this.$(element).find('.chart').tooltip({
                            title: 'Episode is downloading - {0}% {1}'.format(progress.toFixed(1), releaseTitle),
                            container: '.fc-content'
                        });
                    }
                }
            },
            
            _getEvents: function (view) {
                var start = view.start.toISOString();
                var end = view.end.toISOString();

                this.$el.fullCalendar('removeEvents');

                this.collection.fetch({
                    data   : { start: start, end: end },
                    success: this._setEventData.bind(this)
                });
            },

            _setEventData: function (collection) {
                var events = [];

                var self = this;

                collection.each(function (model) {
                    var seriesTitle = model.get('series').title;
                    var start = model.get('airDateUtc');
                    var runtime = model.get('series').runtime;
                    var end = moment(start).add('minutes', runtime).toISOString();

                    var event = {
                        title       : seriesTitle,
                        start       : moment(start),
                        end         : moment(end),
                        allDay      : false,
                        statusLevel : self._getStatusLevel(model, end),
                        downloading : QueueCollection.findEpisode(model.get('id')),
                        model       : model
                    };

                    events.push(event);
                });

                this.$el.fullCalendar('addEventSource', events);
            },

            _getStatusLevel: function (element, endTime) {
                var hasFile = element.get('hasFile');
                var downloading = QueueCollection.findEpisode(element.get('id')) || element.get('grabbed');
                var currentTime = moment();
                var start = moment(element.get('airDateUtc'));
                var end = moment(endTime);

                var statusLevel = 'primary';

                if (hasFile) {
                    statusLevel = 'success';
                }

                else if (downloading) {
                    statusLevel = 'purple';
                }

                else if (currentTime.isAfter(start) && currentTime.isBefore(end)) {
                    statusLevel = 'warning';
                }

                else if (start.isBefore(currentTime) && !hasFile) {
                    statusLevel = 'danger';
                }

                else if (element.get('episodeNumber') === 1) {
                    statusLevel = 'premiere';
                }

                if (end.isBefore(currentTime.startOf('day'))) {
                    statusLevel += ' past';
                }

                return statusLevel;
            },

            _reloadCalendarEvents: function () {
                this.$el.fullCalendar('removeEvents');
                this._setEventData(this.collection);
            },

            _getOptions: function () {
                var options = {
                    allDayDefault : false,
                    weekMode      : 'variable',
                    firstDay      : UiSettings.get('firstDayOfWeek'),
                    timeFormat    : 'h(:mm)a',
                    viewRender    : this._viewRender.bind(this),
                    eventRender   : this._eventRender.bind(this),
                    eventClick    : function (event) {
                        vent.trigger(vent.Commands.ShowEpisodeDetails, {episode: event.model});
                    }
                };

                if ($(window).width() < 768) {
                    options.defaultView = Config.getValue(this.storageKey, 'basicDay');

                    options.header = {
                        left  : 'prev,next today',
                        center: 'title',
                        right : 'basicWeek,basicDay'
                    };
                }

                else {
                    options.defaultView = Config.getValue(this.storageKey, 'basicWeek');

                    options.header = {
                        left  : 'prev,next today',
                        center: 'title',
                        right : 'month,basicWeek,basicDay'
                    };
                }

                options.titleFormat = {
                    month : 'MMMM YYYY',
                    week  : UiSettings.get('shortDateFormat'),
                    day   : UiSettings.get('longDateFormat')
                };

                options.columnFormat = {
                    month : 'ddd',    // Mon
                    week  : UiSettings.get('calendarWeekColumnHeader'),
                    day   : 'dddd'      // Monday
                };

                options.timeFormat = {
                    'default': UiSettings.get('timeFormat')
                };

                return options;
            },

            _addStatusIcon: function (element, icon, tooltip) {
                this.$(element).find('.fc-event-time')
                    .after('<span class="status pull-right"><i class="{0}"></i></span>'.format(icon));

                this.$(element).find('.status').tooltip({
                    title: tooltip,
                    container: '.fc-content'
                });
            }
        });
    });
