/*!
 * Ark Calendar v1.0.1-0 (2016-09-13)
 * http://ark.genesys.com
 * Copyright (c) 2016 Ark Team at Genesys; */

(function(angular) {
  'use strict';

  angular.module('ark.calendar', [
      'ark.core',
      'ark-ui-bootstrap'
    ])
    .constant('arkCalendarConfig', {
      calendars: {}
    });
})(angular);

(function(angular) {
  'use strict';

  // input box focus
  // focuses the title input box if the displayTitle in blockModalConfig is set
  // to true
  angular.module('ark.calendar')
    .directive('focus', ['$timeout',
      function($timeout) {
        return {
          scope: {
            trigger: '@focus'
          },
          link: function(scope, element) {
            scope.$watch('trigger', function() {
              $timeout(function() {
                element[0].focus();
              });
            });
          }
        };
      }
    ]);
})(angular);

(function(angular) {
  'use strict';

  angular.module('ark.calendar')
    .controller('arkCalendarCtrl', ['$scope', '$locale',
      function($scope, $locale) {
        var eventSerialId = 1;
        var sources = $scope.eventSources;
        var sourceSerialId = 1;
        var sourceEventsSerialId = 1;
        var extraEventSignature = $scope.calendarWatchEvent ? $scope.calendarWatchEvent : angular.noop;

        var wrapFunctionWithScopeApply = function(functionToWrap) {
          return function() {
            // This may happen outside of angular context, so create one if outside.

            if ($scope.$root.$$phase) {
              return functionToWrap.apply(this, arguments);
            } else {
              var args = arguments;
              var self = this;
              return $scope.$root.$apply(function() {
                return functionToWrap.apply(self, args);
              });
            }
          };
        };

        // @return {String} fingerprint of the event object and its properties
        this.eventFingerprint = function(e) {
          if (!e._id) {
            e._id = eventSerialId++;
          }

          var extraSignature = extraEventSignature({
            event: e
          }) || '';
          var start = moment.isMoment(e.start) ? e.start.unix() : (e.start ? moment(e.start).unix() : '');
          var end = moment.isMoment(e.end) ? e.end.unix() : (e.end ? moment(e.end).unix() : '');

          // This extracts all the information we need from the event. http://jsperf.com/angular-calendar-events-fingerprint/3
          return '' + e._id + (e.id || '') + (e.title || '') + (e.url || '') + start + end +
            (e.allDay || '') + (e.className || '') + extraSignature;
        };

        // @return {String} fingerprint of the source object and its events array
        this.sourceFingerprint = function(source) {
          var fp = '' + (source.__id || (source.__id = sourceSerialId++));
          var events = angular.isObject(source) && source.events;
          if (events) {
            fp = fp + '-' + (events.__id || (events.__id = sourceEventsSerialId++));
          }
          return fp;
        };

        // @return {Array} all events from all sources
        this.allEvents = function() {
          // do sources.map(&:events).flatten(), but we don't have flatten
          var arraySources = [];
          for (var i = 0, srcLen = sources.length; i < srcLen; i++) {
            var source = sources[i];
            if (angular.isArray(source)) {
              // event source as array
              arraySources.push(source);
            } else if (angular.isObject(source) && angular.isArray(source.events)) {
              // event source as object, ie extended form
              var extEvent = {};
              for (var key in source) {
                if (key !== '_id' && key !== 'events') {
                  extEvent[key] = source[key];
                }
              }
              for (var eI = 0; eI < source.events.length; eI++) {
                angular.extend(source.events[eI], extEvent);
              }
              arraySources.push(source.events);
            }
          }
          return Array.prototype.concat.apply([], arraySources);
        };

        // Track changes in array of objects by assigning id tokens to each element and watching the scope for changes in the tokens
        // @param {Array|Function} arraySource array of objects to watch
        // @param tokenFn {Function} that returns the token for a given object
        // @return {Object}
        //  subscribe: function(scope, function(newTokens, oldTokens))
        //    called when source has changed. return false to prevent individual callbacks from firing
        //  onAdded/Removed/Changed:
        //    when set to a callback, called each item where a respective change is detected
        this.changeWatcher = function(arraySource, tokenFn) {
          var self;
          var getTokens = function() {
            var array = angular.isFunction(arraySource) ? arraySource() : arraySource;
            var result = [];
            var token;
            var el;
            for (var i = 0, n = array.length; i < n; i++) {
              el = array[i];
              token = tokenFn(el);
              map[token] = el;
              result.push(token);
            }
            return result;
          };

          // @param {Array} a
          // @param {Array} b
          // @return {Array} elements in that are in a but not in b
          // @example
          //  subtractAsSets([6, 100, 4, 5], [4, 5, 7]) // [6, 100]
          var subtractAsSets = function(a, b) {
            var result = [];
            var inB = {};
            var i;
            var n;
            for (i = 0, n = b.length; i < n; i++) {
              inB[b[i]] = true;
            }
            for (i = 0, n = a.length; i < n; i++) {
              if (!inB[a[i]]) {
                result.push(a[i]);
              }
            }
            return result;
          };

          // Map objects to tokens and vice-versa
          var map = {};

          // Compare newTokens to oldTokens and call onAdded, onRemoved, and onChanged handlers for each affected event respectively.
          var applyChanges = function(newTokens, oldTokens) {
            var i, n, el, token;
            var replacedTokens = {};
            var removedTokens = subtractAsSets(oldTokens, newTokens);
            for (i = 0, n = removedTokens.length; i < n; i++) {
              var removedToken = removedTokens[i];
              el = map[removedToken];
              delete map[removedToken];
              var newToken = tokenFn(el);
              // if the element wasn't removed but simply got a new token, its old token will be different from the current one
              if (newToken === removedToken) {
                self.onRemoved(el);
              } else {
                replacedTokens[newToken] = removedToken;
                self.onChanged(el);
              }
            }

            var addedTokens = subtractAsSets(newTokens, oldTokens);
            for (i = 0, n = addedTokens.length; i < n; i++) {
              token = addedTokens[i];
              el = map[token];
              if (!replacedTokens[token]) {
                self.onAdded(el);
              }
            }
          };
          self = {
            subscribe: function(scope, onArrayChanged) {
              scope.$watch(getTokens, function(newTokens, oldTokens) {
                var notify = !(onArrayChanged && onArrayChanged(newTokens, oldTokens) === false);
                if (notify) {
                  applyChanges(newTokens, oldTokens);
                }
              }, true);
            },
            onAdded: angular.noop,
            onChanged: angular.noop,
            onRemoved: angular.noop
          };
          return self;
        };

        this.getFullCalendarConfig = function(calendarSettings, arkCalendarConfig) {
          var config = {};

          angular.extend(config, arkCalendarConfig);
          angular.extend(config, calendarSettings);

          angular.forEach(config, function(value, key) {
            if (typeof value === 'function') {
              config[key] = wrapFunctionWithScopeApply(config[key]);
            }
          });

          return config;
        };

        this.getLocaleConfig = function(fullCalendarConfig) {
          if (!fullCalendarConfig.lang || fullCalendarConfig.useNgLocale) {
            // Configure to use locale names by default
            var tValues = function(data) {
              // convert {0: "Jan", 1: "Feb", ...} to ["Jan", "Feb", ...]
              var r, k;
              r = [];
              for (k in data) {
                if (data.hasOwnProperty(k)) {
                  r[k] = data[k];
                }
              }
              return r;
            };
            var dtf = $locale.DATETIME_FORMATS;
            return {
              monthNames: tValues(dtf.MONTH),
              monthNamesShort: tValues(dtf.SHORTMONTH),
              dayNames: tValues(dtf.DAY),
              dayNamesShort: tValues(dtf.SHORTDAY)
            };
          }
          return {};
        };
      }
    ]);
})(angular);

(function(angular) {
  'use strict';

  angular.module('ark.calendar')
    .directive('arkCalendar', ['arkCalendarConfig', '$compile', '$timeout', '$modal', '$interval',
      function(arkCalendarConfig, $compile, $timeout, $modal) {
        return {
          restrict: 'A',
          scope: {
            eventSources: '=ngModel',
            calendarWatchEvent: '&'
          },
          controller: 'arkCalendarCtrl',

          link: function(scope, elm, attrs, controller) {

            /* Scope Variables */

            scope.genericCheckbox = {};
            scope.filterDate = {};
            scope.isAgendaDay = false;
            scope.datepickerDate = {};

            var sources = scope.eventSources;
            var sourcesChanged = false;
            var calendar;
            var eventSourcesWatcher = controller.changeWatcher(sources, controller.sourceFingerprint);
            var eventsWatcher = controller.changeWatcher(controller.allEvents, controller.eventFingerprint);
            var options = null;

            // MODIFIED FROM ORIGINAL
            // getCalendarOptions function is called to get options, instead of doing that directly
            function getOptions() {
              var calendarSettings = attrs.arkCalendar ? getCalendarOptions() : {};
              var fullCalendarConfig = controller.getFullCalendarConfig(calendarSettings, arkCalendarConfig);

              var localeFullCalendarConfig = controller.getLocaleConfig(fullCalendarConfig);
              angular.extend(localeFullCalendarConfig, fullCalendarConfig);
              options = {
                eventSources: sources
              };
              angular.extend(options, localeFullCalendarConfig);
              // remove calendars from options
              options.calendars = null;

              var options2 = {};
              for (var o in options) {
                if (o !== 'eventSources') {
                  options2[o] = options[o];
                }
              }
              return JSON.stringify(options2);
            }

            // ADDED TO ORIGINAL
            function getCalendarOptions() { // Direct access to user's calendar config
              return scope.$parent.$eval(attrs.arkCalendar);
            }

            // ADDED TO ORIGINAL:
            // gets the localized names to be passed into the modals
            scope.getDayNames = function() {
              var calendarSettings = attrs.arkCalendar ? getCalendarOptions() : {};
              var fullCalendarConfig = controller.getFullCalendarConfig(calendarSettings, arkCalendarConfig);
              var localeConfig = controller.getLocaleConfig(fullCalendarConfig);
              return localeConfig;
            };

            // ADDED TO ORIGINAL:
            // open a modal to create an event
            scope.openBlockModal = function(startEndInfo, task) {
              $modal.open({
                templateUrl: 'templates/blockModal.html',
                controller: 'blockModalCtrl',
                windowClass: 'modal fade in',
                resolve: {
                  bindings: function() { //Controller
                    return {
                      'config': getCalendarOptions(),
                      'eventSources': scope.eventSources,
                      'hiddenDaysArr': calendar.fullCalendar('getCalendar').view.isHiddenDayHash
                    };
                  },
                  event: function() {
                    return startEndInfo;
                  },
                  task: function() {
                    return task;
                  },
                  calendar: function() {
                    return calendar;
                  }
                }
              });
            };

            // ADDED TO ORIGINAL:
            // allow the user to change the config through a modal
            scope.openSettings = function() {
              var options = getCalendarOptions();
              if (options.settingsModal) {
                options.settingsModal();
              } else {
                $modal.open({
                  templateUrl: 'templates/settingsTemplate.html',
                  controller: 'SettingsCtrl',
                  resolve: {
                    bindings: function() {
                      return {
                        'hiddenDaysArr': calendar.fullCalendar('getCalendar').view.isHiddenDayHash,
                        'config': getCalendarOptions(),
                        'eventSources': scope.eventSources,
                        'nameConfig': scope.getDayNames()
                      };
                    }
                  }
                });
              }
            };

            // ADDED TO ORIGINAL:
            // keeps track of when the ark-datepicker is opened
            scope.openDatepicker = function($event) {
              $event.preventDefault();
              $event.stopPropagation();
              scope.datepickerOpened = !scope.datepickerOpened;
            };

            // ADDED TO ORIGINAL:
            // changes the date of the calendar if the user has selected a new date in the ark-datepicker
            scope.dateChangedStart = function() {
              calendar.fullCalendar('gotoDate', scope.filterDate.start);
              var view = calendar.fullCalendar('getView');
              scope.updateDatepicker(view);
            };

            // ADDED TO ORIGINAL:
            // regular office hours view acts as a template to set up repeating events - there are no dates displayed in datepicker
            // in other view - display dates for datepicker
            scope.updateDatepicker = function(view) {
              if (!options.generic) {
                var dateStart = view.intervalStart.clone().local().format('MMMM D, YYYY');
                var dateEnd = view.intervalEnd.clone().subtract(1, 'second').local().format('MMMM D, YYYY');
                scope.filterDate = {
                  start: dateStart,
                  end: dateEnd
                };
              } else {
                scope.filterDate = {
                  start: 'N/A',
                  end: 'N/A'
                };
              }
            };

            // ADDED TO ORIGINAL:
            // display full date if in non-regular office hours view (ex. Sun 10/18)
            // display only days of week for regular office hours view (ex. Sunday)
            scope.changeDates = function() {
              var calendarOptions = getCalendarOptions();
              if (calendarOptions) {
                if (!scope.genericCheckbox.checked) {
                  calendarOptions.columnFormat = options.genericColumnFormat || {
                    day: 'dddd MM/DD',
                    week: 'ddd MM/DD',
                    month: 'dddd'
                  };
                  calendarOptions.generic = false;
                } else {
                  calendarOptions.columnFormat = options.nonGenericColumnFormat || {
                    day: 'dddd',
                    week: 'dddd'
                  };
                  calendarOptions.generic = true;
                }
              }
            };

            // ADDED TO ORIGINAL:
            // display full date if in non-regular office hours view (ex. Sun 10/18)
            // display only days of week for regular office hours view (ex. Sunday)
            scope.initializeDates = function() {
              if (!scope.genericCheckbox.checked) {
                options.columnFormat = options.genericColumnFormat || {
                  day: 'dddd MM/DD',
                  week: 'ddd MM/DD',
                  month: 'dddd'
                };
                options.generic = false;
              } else {
                options.columnFormat = options.nonGenericColumnFormat || {
                  day: 'dddd',
                  week: 'dddd'
                };
                options.generic = true;
              }
            };

            // ADDED TO ORIGINAL:
            // Click date to change view
            scope.switchDayView = function(date) {
              date = new Date(date);
              calendar.fullCalendar('changeView', 'agendaDay');
              calendar.fullCalendar('gotoDate', moment(date));
            };

            // ADDED to original
            // provides additional functionality and allows user to pass in custom callbacks
            // unselectModalCallback - opens a modal on event creation
            // eventClick - opens a model on event click to update/delete event
            // viewRender -
            // eventRender - displays tooltips and highlights events with similarId
            // setVariables - initialize scope variables
            function initialize() { // Initialize things before actual calendar creation

              options.unselectModalCallback = function(startEndInfo) { // custom callback to open up a modal whenever a selection is made
                var view = calendar.fullCalendar('getView');
                if (!(view.name === 'month' && (options.switchOnMonthDayClick ||
                    options.switchOnMonthDayClick === undefined)) &&
                  options.editable || options.editable === undefined) {
                  scope.openBlockModal(startEndInfo, 'create');
                }
              };

              var eventClickFunction = options.eventClick;
              options.eventClick = function(event, jsEvent, view) {
                if (eventClickFunction) {
                  eventClickFunction(event, jsEvent, view);
                }
                if (options.editable && (event.editable === undefined || event.editable)) {
                  scope.openBlockModal(event, 'edit');
                }
              };

              var viewRenderFunction = options.viewRender;
              options.viewRender = function(view, element) {
                if (viewRenderFunction) {
                  viewRenderFunction(view, element); // Call function provided by user
                }
                scope.isAgendaDay = (view.name === 'agendaDay' || view.name === 'basicDay');

                $timeout(function() {
                  scope.updateDatepicker(view);
                });
                $compile(element)(scope);
              };

              scope.highlight = {};
              scope.highlight.id = '-1';

              var eventRenderFunction = options.eventRender;
              options.eventRender = function(event, element, view) {
                if (eventRenderFunction) {
                  eventRenderFunction(event, element, view);
                }
                if (options.highlightSimilarId) {
                  element.attr({
                    'ng-class': '{\'event-highlight\': highlight.id == "' + event._id + '"}',
                    'ng-mouseenter': 'highlight.id ="' + event._id + '"',
                    'ng-mouseleave': 'highlight.id ="-1"'
                  });
                }

                // manually remove existing tooltips otherwise they persist if the user tries to drag and drop the event
                if (options.tooltips) {
                  angular.element('.tooltip.top.in').remove();
                }

                if ((!event.allDay || options.showAllDayText || event.showAllDayText) && options.tooltips) {
                  var text;
                  // Allday events do not have an end time
                  if (event.tooltipText) {
                    text = event.tooltipText;
                  }
                  // want to append to body to avoid some undesirable behaviours:
                  // the tooltips go behind all day row for events in the top row if append to body is false
                  // the tooltips show up far away from the event if append to body is false
                  var timetext = event.start.clone().format('h:mm A') + ' - ' +
                    (event.end ? event.end.format('h:mm A') : event.start.clone().add(2, 'hours').format('h:mm A'));
                  element.attr({
                    'tooltip-placement': 'top',
                    'tooltip-animation': false,
                    'tooltip-append-to-body': true,
                    'tooltip': text || timetext
                  });
                }
                $compile(element)(scope);
              };
            }

            function setVariables() {
              // Datepicker
              scope.dateOptions = {
                startingDay: options.firstDay || 0
              };

              // Checkbox
              scope.genericCheckbox.checked = options.generic || false;

              scope.initializeDates();
            }

            scope.$on('$destroy', function() {
              scope.destroyCalendar();
            });

            scope.destroyCalendar = function() {
              if (calendar && calendar.fullCalendar) {
                var view = calendar.fullCalendar('getView');
                if (view) {
                  if (!options.generic) {
                    options.defaultView = view.name; // 'Store' view, so it doesn't automatically jump back to default - Smoother UX
                  } else {
                    options.defaultView = view.name !== 'month' ? view.name : 'agendaWeek';
                  }
                }
                calendar.fullCalendar('destroy');
              }
              if (attrs.calendar) {
                calendar = arkCalendarConfig.calendars[attrs.calendar] = $(elm).html('');
              } else {
                calendar = $(elm).html('');
              }
            };

            // MODIFIED FROM ORIGINAL:
            // change the constant to make sure that the calendar is defined
            // before processing callbacks
            scope.initCalendar = function() {
              // Update datepicker on view changes
              initialize();
              setVariables();
              if (!calendar) {
                calendar = angular.element(elm).html('');
              }
              if (attrs.calendar) {
                arkCalendarConfig.calendars[attrs.calendar] = calendar;
              }
              calendar.fullCalendar(options);

              // compile the elements to make sure interpolated elements are evaluated
              $compile(elm.contents())(scope);
            };

            eventSourcesWatcher.onAdded = function(source) {
              if (calendar && calendar.fullCalendar) {
                calendar.fullCalendar(options);
                if (attrs.calendar) {
                  arkCalendarConfig.calendars[attrs.calendar] = calendar;
                }
                calendar.fullCalendar('addEventSource', source);
                sourcesChanged = true;
              }
            };

            eventSourcesWatcher.onRemoved = function(source) {
              if (calendar && calendar.fullCalendar) {
                calendar.fullCalendar('removeEventSource', source);
                sourcesChanged = true;
              }
            };

            eventSourcesWatcher.onChanged = function() {
              if (calendar && calendar.fullCalendar) {
                calendar.fullCalendar('refetchEvents');
                sourcesChanged = true;
              }
            };

            eventsWatcher.onAdded = function(event) {
              if (calendar && calendar.fullCalendar) {
                calendar.fullCalendar('renderEvent', event, (event.stick ? true : false));
              }
            };

            eventsWatcher.onRemoved = function(event) {
              if (calendar && calendar.fullCalendar) {
                calendar.fullCalendar('removeEvents', event._id);
              }
            };

            eventsWatcher.onChanged = function(event) {
              if (calendar && calendar.fullCalendar) {
                var clientEvents = calendar.fullCalendar('clientEvents', event._id);
                for (var i = 0; i < clientEvents.length; i++) {
                  var clientEvent = clientEvents[i];
                  clientEvent = angular.extend(clientEvent, event);
                  calendar.fullCalendar('updateEvent', clientEvent);
                }
              }
            };

            eventSourcesWatcher.subscribe(scope);
            eventsWatcher.subscribe(scope, function() {
              if (sourcesChanged === true) {
                sourcesChanged = false;
                // return false to prevent onAdded/Removed/Changed handlers from firing in this case
                return false;
              }
            });

            scope.$watch(getOptions, function(newValue, oldValue) {
              if (newValue !== oldValue) {
                scope.destroyCalendar();
                scope.initCalendar();
              } else if ((newValue && angular.isUndefined(calendar))) {
                scope.initCalendar();
              }
            });

            this.$onInit = function(){
              scope.initCalendar();
            }

          }
        };
      }
    ]);
})(angular);

(function(angular) {
  'use strict';

  angular.module('ark.calendar')
    .controller('blockModalCtrl', ['$scope', 'bindings', 'event', 'task', 'calendar',
      function($scope, bindings, event, task, calendar) {

        /* Helper Functions */
        function getEventConfigProperties(id, blockConfig) {
          for (var item in blockConfig) {
            if (blockConfig[item].id === id) {
              return blockConfig[item];
            }
          }
          return false;
        }

        function minutesOfDay(m) {
          return m.minutes() + m.hours() * 60;
        }

        function inMinutes(m) {
          return m.minutes() + m.hours() * 60 + m.days() * 24 * 60;
        }

        function getMomentWithDistance(moment, distance) { // returns a new Moment that is distance days away from the given Moment
          var newMoment = moment.clone(); // example: getMomentWithDistance(Moment(01.20.15), -5) === Moment(01.15.15)
          newMoment.add(distance, 'days');
          return newMoment;
        }

        function getMomentObjectWithLabel(array, label) { // Get first object with matching label.
          for (var i = 0; i < array.length; i++) { // (eg. getMomentObjectWithLabel([{'label:'Tuesday'}, {'label':'Wednesday'}], 'Wednesday') -> {'label':'Wednesday'})
            if (array[i].label === label) {
              return array[i];
            }
          }
        }

        function grabConfigValue(key) {
          return (bindings.config.generic ? (genericConfig[key] || blockConfig[key]) : blockConfig[key]);
        }

        /* Variables */
        var genericConfig = bindings.config.genericBlockModalConfig;
        if (!genericConfig) {
          genericConfig = {};
        }
        var blockConfig = bindings.config.blockModalConfig;
        if (!blockConfig) {
          blockConfig = {};
        }

        $scope.generic = bindings.config.generic;
        $scope.blockName = grabConfigValue('blockName');
        $scope.blockNamePlaceholder = grabConfigValue('blockNamePlaceholder');
        $scope.blockDescription = grabConfigValue('blockDescription');
        $scope.blockDescriptionPlaceholder = grabConfigValue('blockDescriptionPlaceholder');
        $scope.blockType = grabConfigValue('blockType');
        $scope.blockTimeSlot = grabConfigValue('blockTimeSlot');
        $scope.errorMessage = grabConfigValue('errorMessage');
        $scope.allDayEventLabel = grabConfigValue('allDayEventLabel');
        $scope.isAnnualLabel = grabConfigValue('isAnnualLabel');
        $scope.cancelButtonLabel = grabConfigValue('cancelButtonLabel');
        $scope.deleteButtonLabel = grabConfigValue('deleteButtonLabel');
        $scope.updateButtonLabel = grabConfigValue('updateButtonLabel');
        $scope.createButtonLabel = grabConfigValue('createButtonLabel');
        $scope.fromLabel = grabConfigValue('fromLabel');
        $scope.toLabel = grabConfigValue('toLabel');
        $scope.weeksSelectedLabel = grabConfigValue('weeksSelectedLabel');
        $scope.forDaysLabel = grabConfigValue('forDaysLabel');
        $scope.hours = grabConfigValue('hours');
        $scope.durationError = grabConfigValue('durationError') || '';
        $scope.hiddenDays = bindings.config.hiddenDays;
        $scope.hiddenDaysArr = [false, false, false, false, false, false, false];
        $scope.customErrorEventAllocate = grabConfigValue('customErrorEventAllocate');
        $scope.customErrorEventDelete = grabConfigValue('customErrorEventDelete');
        $scope.customErrorEventMessage = grabConfigValue('customErrorEventMessage');
        $scope.noDateSelectedErrorMessage = grabConfigValue('noDateSelectedErrorMessage');
        $scope.deleteErrorPrefix = grabConfigValue('deleteErrorPrefix');
        $scope.allocateErrorPrefix = grabConfigValue('allocateErrorPrefix');

        $scope.error = '';
        $scope.dateError = '';
        $scope.isAnnual = false;

        $scope.task = task;
        $scope.multiDay = true;
        $scope.multiEvents = false;
        $scope.updateEvents = [];

        $scope.displayTitle = grabConfigValue('displayTitle') || '';
        $scope.displayDescription = grabConfigValue('displayDescription') || '';
        var validRadios = $scope.generic ? genericConfig.radios || blockConfig.radios : blockConfig.radios;
        var i;

        if (task === 'create') {
          if ($scope.customErrorEventAllocate) {
            $scope.error = $scope.allocateErrorPrefix + $scope.customErrorEventMessage;
          }
          $scope.blockTitle = grabConfigValue('displayBlockTitleCreate');
          $scope.title = grabConfigValue('title');
          $scope.configId = 0;
        } else if (task === 'edit') {
          if ($scope.customErrorEventDelete && $scope.customErrorEventAllocate) {
            $scope.error = $scope.customErrorEventMessage;
          } else if ($scope.customErrorEventAllocate) {
            $scope.error = $scope.allocateErrorPrefix + $scope.customErrorEventMessage;
          } else if ($scope.customErrorEventDelete) {
            $scope.error = $scope.deleteErrorPrefix + $scope.customErrorEventMessage;
          }
          $scope.blockTitle = grabConfigValue('displayBlockTitleModify');
          $scope.title = event.title;
          $scope.description = event.description;
          $scope.configId = event.configId;
          $scope.updateEvents = calendar.fullCalendar('clientEvents', event._id);
          $scope.multiEvents = $scope.updateEvents.length > 1;
          $scope.isAnnual = event.isAnnual;
        }

        $scope.blockConfig = jQuery.extend(true, {}, bindings.config.blockConfig); // Clone to prevent config from changing when used on ng-repeat TODO: Make this not use JQuery

        if ($scope.hiddenDays) {
          for (i = 0; i < $scope.hiddenDays.length; i++) {
            var ind = $scope.hiddenDays[i];
            $scope.hiddenDaysArr[ind] = true;
          }
        }

        $scope.radioOptionsSelect = {};

        if (validRadios) {
          for (var item in $scope.blockConfig) {
            if (validRadios.indexOf($scope.blockConfig[item].id) === -1) {
              delete $scope.blockConfig[item];
            }
          }
          if (validRadios.indexOf(event.configId) === -1) {
            $scope.configId = validRadios[0];
          }
        }

        $scope.allDayEvent = event.start.hour() === 0 && event.start.minute() === 0 &&
          event.start.clone().add(Math.floor(moment.duration(event.end.clone().diff(event.start)).asDays()), 'day')
          .format('MM DD YYYY HH mm') === event.end.format('MM DD YYYY HH mm');

        if ($scope.blockConfig && $scope.blockConfig[$scope.configId]) {
          $scope.radioOptionsSelect.radioSelect = $scope.configId;
        }

        $scope.$watch('isAnnual', function(newValue, oldValue) {
          $scope.renderWeeksSelected();
        });

        $scope.$watch('radioOptionsSelect.radioSelect', function() {
          if ($scope.blockConfig[$scope.radioOptionsSelect.radioSelect].allDay === true) {
            $scope.allDayEvent = true;
            $scope.editable = false;
          } else {
            $scope.editable = true;
            // update the allDayEvent
            $scope.allDayEvent = event.start.hour() === 0 && event.start.minute() === 0 &&
              event.start.clone().add(Math.floor(moment.duration(event.end.clone().diff(event.start)).asDays()), 'day')
              .format('MM DD YYYY HH mm') === event.end.format('MM DD YYYY HH mm');
          }
          if ($scope.blockConfig[$scope.radioOptionsSelect.radioSelect].maxDuration) {
            $scope.maxDuration = $scope.blockConfig[$scope.radioOptionsSelect.radioSelect].maxDuration;
          }
        });

        $scope.fromToDays = {
          'fromDay': event.start.format('dddd'),
          'toDay': event.end.clone().subtract(1, 'second').format('dddd')
        };
        $scope.fromToTimes = {
          'fromTime': event.start.format('hh.mm.A'),
          'toTime': event.end.format('hh.mm.A')
        };

        if ($scope.multiEvents) {
          $scope.fromToDays.toDay = $scope.fromToDays.fromDay;
        }
        
        $scope.renderWeeksSelected = function(){

          // implementation-specific details
          var startDay = event.start.day(); // gets an int representing the day of the week

          var firstDay = bindings.config.firstDay || 0;
          var numDaysFromFirst;

          if (startDay >= firstDay) {
            numDaysFromFirst = startDay - firstDay; // number of days between start and firstDay
          } else {
            numDaysFromFirst = 7 - (firstDay - startDay);
          }

          $scope.days = [];
          $scope.weeks = [];

          var endClone = event.end.clone().subtract(1, 'second');
          var loopStartMoment = getMomentWithDistance(event.start, -numDaysFromFirst);
          var loopEndMoment = getMomentWithDistance(loopStartMoment, 6);
          var value;

          //Days used in generic calendary
          while (!loopStartMoment.isAfter(loopEndMoment)) {
            if ($scope.multiEvents) {
              for (i = 0; i < $scope.updateEvents.length; i++) {
                value = loopStartMoment.isBetween($scope.updateEvents[i].start, endClone) ||
                  loopStartMoment.isSame($scope.updateEvents[i].start, 'day') ||
                  loopStartMoment.isSame(endClone, 'day');
                if (value) {
                  break;
                }
              }
            } else {
              value = loopStartMoment.isBetween(event.start, endClone) ||
                loopStartMoment.isSame(event.start, 'day') ||
                loopStartMoment.isSame(endClone, 'day');
            }
            if (!$scope.hiddenDaysArr[loopStartMoment.day()]) {
              $scope.days.push({
                'label': loopStartMoment.format('dddd'),
                'value': value,
                'moment': loopStartMoment.clone().local().toDate()
              });
            }
            loopStartMoment.add(1, 'day');
          }
          loopStartMoment = getMomentWithDistance(event.start, -numDaysFromFirst);
          loopEndMoment = getMomentWithDistance(loopStartMoment, 6);

          //Weeks used in non generic calednar
          while (!loopStartMoment.isAfter(endClone)) {
            var weekObject = [];
            for (var iteratorMoment = loopStartMoment.clone(); !iteratorMoment.isAfter(loopEndMoment); iteratorMoment.add(1, 'days')) {
              if ($scope.multiEvents) {
                for (i = 0; i < $scope.updateEvents.length; i++) {
                  value = iteratorMoment.isBetween($scope.updateEvents[i].start, endClone) ||
                    iteratorMoment.isSame($scope.updateEvents[i].start, 'day') ||
                    iteratorMoment.isSame(endClone, 'day');
                  if (value) {
                    break;
                  }
                }
              } else {
                value = iteratorMoment.isBetween(event.start, endClone) ||
                  iteratorMoment.isSame(event.start, 'day') ||
                  iteratorMoment.isSame(endClone, 'day');
              }
  
              if (!$scope.hiddenDaysArr[iteratorMoment.day()]) {
                weekObject.push({
                  'label': $scope.isAnnual ? iteratorMoment.format('MM/DD') : iteratorMoment.format('MM/DD') + ' (' + iteratorMoment.format('dddd') + ')',
                  'value': value,
                  'moment': iteratorMoment.clone().local().toDate()
                }); // isBetween is exclusive, not inclusive
              }
            }
            $scope.weeks.push({
              'weekLabel': $scope.isAnnual ? loopStartMoment.format('MM/DD') + ' - ' + loopEndMoment.format('MM/DD') : loopStartMoment.format('MM/DD/YYYY') + ' - ' + loopEndMoment.format('MM/DD/YYYY'),
              'days': weekObject
            });
            loopStartMoment.add(7, 'days');
            loopEndMoment.add(7, 'days');
          }

        }

        $scope.renderWeeksSelected();


        //Validates that at least one date is checked.
        //Runs every time a date is selected/unselected.
        $scope.validateSelectedDates = function() {
          var atLeastOneChecked = false;
          //Go through each day and make sure at least one is checked off
          if (!$scope.generic) {
            for (var i = 0; i < $scope.weeks.length; i++) {
              for (var j = 0; j < $scope.weeks[i].days.length; j++) {
                if ($scope.weeks[i].days[j].value) {
                  atLeastOneChecked = true;
                }
              }
            }
          } else {
            for (var k = 0; k < $scope.days.length; k++) {
              if ($scope.days[k].value) {
                atLeastOneChecked = true;
              }
            }
          }
          if (!atLeastOneChecked) {
            $scope.dateError = $scope.noDateSelectedErrorMessage;
          } else if (atLeastOneChecked && $scope.customErrorEventAllocate) {
            $scope.dateError = '';
            //$scope.error = $scope.customErrorEventMessage;
          } else {
            $scope.error = '';
            $scope.dateError = '';
          }
        };

        /* Block creation/modification/deletion */ // Add a debounce mechanism to prevent rapid creation of blocks

        $scope.create = function() {
          $scope.error = '';

          var endMin, startMin;
          var newEvent = {};
          var eventsToRender = [];
          newEvent.title = $scope.title;
          var tempMoment;
          var timeStamp;
          var eventObject;

          var configProperty = getEventConfigProperties($scope.radioOptionsSelect.radioSelect, $scope.blockConfig);

          var timeStart = moment($scope.fromToTimes.fromTime, ['hh.mm.A']);
          var timeEnd = moment($scope.fromToTimes.toTime, ['hh.mm.A']);

          newEvent.start = event.start.clone();
          newEvent.end = event.end.clone().subtract(1, 'second');

          newEvent.start.hour(timeStart.hour()).minute(timeStart.minute()).second(0);
          newEvent.end.hour(timeEnd.hour()).minute(timeEnd.minute()).second(0);

          endMin = inMinutes(timeEnd);
          startMin = inMinutes(timeStart);

          if ($scope.maxDuration && (endMin - startMin) > $scope.maxDuration * 60) {
            $scope.error = $scope.durationError + ' ' + $scope.maxDuration + ' ' + $scope.hours;
          } else {
            if (!$scope.generic) {
              for (var i = 0; i < $scope.weeks.length; i++) {
                for (var j = 0; j < $scope.weeks[i].days.length; j++) {
                  if ($scope.weeks[i].days[j].value) {
                    tempMoment = moment($scope.weeks[i].days[j].moment);
                    newEvent.start.dayOfYear(tempMoment.dayOfYear()).year(tempMoment.year());
                    newEvent.end.dayOfYear(tempMoment.dayOfYear()).year(tempMoment.year());
                    if ($scope.allDayEvent || minutesOfDay(newEvent.start) >= minutesOfDay(newEvent.end)) {
                      newEvent.end.add(1, 'day');
                    }
                    timeStamp = moment().format('YYYY-MM-DD HH:mm:SSS');
                    eventObject = {
                      title: newEvent.title,
                      description: $scope.description,
                      allDay: $scope.allDayEvent,
                      start: newEvent.start.clone().local().toDate(),
                      end: newEvent.end.clone().local().toDate(),
                      leftBorderColor: configProperty.leftBorderColor || event.leftBorderColor,
                      icon: configProperty.icon || event.icon,
                      configId: configProperty.id,
                      timeStamp: timeStamp,
                      isAnnual: $scope.isAnnual
                    };
                    eventsToRender.push(eventObject);
                    calendar.fullCalendar('renderEvent', eventObject);
                  }
                }
              }
            } else {
              for (var k = 0; k < $scope.days.length; k++) {
                if ($scope.days[k].value) {
                  tempMoment = moment($scope.days[k].moment);
                  newEvent.start.dayOfYear(tempMoment.dayOfYear()).year(tempMoment.year());
                  newEvent.end.dayOfYear(tempMoment.dayOfYear()).year(tempMoment.year());
                  if ($scope.allDayEvent || minutesOfDay(newEvent.start) >= minutesOfDay(newEvent.end)) {
                    newEvent.end.add(1, 'day');
                  }
                  timeStamp = moment().format('YYYY-MM-DD HH:mm:SSS');
                  eventObject = {
                    title: newEvent.title,
                    description: $scope.description,
                    allDay: $scope.allDayEvent,
                    start: newEvent.start.clone().local().toDate(),
                    end: newEvent.end.clone().local().toDate(),
                    leftBorderColor: configProperty.leftBorderColor || event.leftBorderColor,
                    icon: configProperty.icon || event.icon,
                    configId: configProperty.id,
                    timeStamp: timeStamp
                  };
                  eventsToRender.push(eventObject);
                  calendar.fullCalendar('renderEvent', eventObject);
                }
              }
            }

            var events = calendar.fullCalendar('clientEvents', function(event) {
              for (var j = 0; j < eventsToRender.length; j++) {
                if (eventsToRender[j].timeStamp === event.timeStamp) {
                  return true;
                }
              }
            });
            if (bindings.config.onBlockCreate) {
              if (events.length) {
                bindings.config.onBlockCreate(events);
              } else {
                bindings.config.onBlockCreate(eventsToRender); // triggers on block creation.
              }
            }
            $scope.$close();
          }
        };

        $scope.update = function() {

          $scope.error = '';

          var endMin, startMin;

          var configProperty = getEventConfigProperties($scope.radioOptionsSelect.radioSelect, $scope.blockConfig);
          var fromObject = getMomentObjectWithLabel($scope.days, $scope.fromToDays.fromDay);
          var toObject = getMomentObjectWithLabel($scope.days, $scope.fromToDays.toDay);
          var timeStart = moment($scope.fromToTimes.fromTime, ['hh.mm.A']);
          var timeEnd = moment($scope.fromToTimes.toTime, ['hh.mm.A']);

          var fromMoment = moment(fromObject.moment);
          var toMoment = moment(toObject.moment);

          var oldEvent = jQuery.extend({}, event);
          // clone the start and end times so that they are preserved
          oldEvent.start = event.start.clone();
          oldEvent.end = event.end.clone();

          var newEvent = {};

          // copy the event times and check for errors
          // if the user clicks cancel the real event will be unchanged
          newEvent.start = event.start.clone();
          newEvent.end = event.end.clone();

          newEvent.start.hour(timeStart.hour()).minute(timeStart.minute());
          newEvent.end.hour(timeEnd.hour()).minute(timeEnd.minutes());

          newEvent.start.year(fromMoment.year());
          newEvent.start.dayOfYear(fromMoment.dayOfYear());
          newEvent.end.year(toMoment.year());
          newEvent.end.dayOfYear(toMoment.dayOfYear());

          if ($scope.multiEvents && minutesOfDay(timeStart) >= minutesOfDay(timeEnd)) {
            newEvent.end.add(1, 'day');
          } else if (bindings.config.resizeNextDay === false && minutesOfDay(timeEnd) === 0) {
            newEvent.end.add(1, 'day');
          }

          endMin = inMinutes(newEvent.end);
          startMin = inMinutes(newEvent.start);

          // if maxDuration exists make sure the event does not exceed it
          if ($scope.maxDuration && (endMin - startMin) > $scope.maxDuration * 60) {
            $scope.error = $scope.durationError + ' ' + $scope.maxDuration + ' ' + $scope.hours;
          } else {
            // Look into this in the future.  Some weird time bug, where comparing the times with isBefore isn't working properly
            if (newEvent.start.format('MM DD YYYY') === newEvent.end.format('MM DD YYYY') && (minutesOfDay(newEvent.start) >= minutesOfDay(newEvent.end)) && (!$scope.allDayEvent)) {
              $scope.error = $scope.errorMessage;
            } else if ((newEvent.start.clone().isAfter(newEvent.end.clone()))) {
              $scope.error = $scope.errorMessage;
            } else {
              // there are no errors, update the event
              event.title = $scope.title;
              event.description = $scope.description;
              event.allDay = $scope.allDayEvent;

              event.leftBorderColor = configProperty.leftBorderColor || event.leftBorderColor;
              event.icon = configProperty.icon || event.icon;
              event.configId = configProperty.id;

              event.start.hour(timeStart.hour()).minute(timeStart.minute());
              event.end.hour(timeEnd.hour()).minute(timeEnd.minutes());

              event.start.year(fromMoment.year());
              event.start.dayOfYear(fromMoment.dayOfYear());
              event.end.year(toMoment.year());
              event.end.dayOfYear(toMoment.dayOfYear());
              event.isAnnual = $scope.isAnnual;

              if ($scope.multiEvents && minutesOfDay(timeStart) >= minutesOfDay(timeEnd)) {
                event.end.add(1, 'day');
              } else if (bindings.config.resizeNextDay === false && minutesOfDay(timeEnd) === 0) {
                event.end.add(1, 'day');
              }

              calendar.fullCalendar('updateEvent', event, (event.allDay === false && event.allDay !== event._allDay));
              if (bindings.config.onBlockUpdate) {
                bindings.config.onBlockUpdate(event, oldEvent); // triggers on block update. //new event, old event
              }
              $scope.$close();
            }
          }
        };

        $scope.remove = function() {
          calendar.fullCalendar('removeEvents', event._id);
          if (bindings.config.onBlockDelete) {
            bindings.config.onBlockDelete(event); // triggers on block update.
          }
          $scope.$close();
        };

        $scope.cancel = function() {
          $scope.$close();
        };
      }
    ]);
})(angular);

(function(angular) {
  'use strict';

  angular.module('ark.calendar')
    .controller('SettingsCtrl',
      ['$scope', '$modalInstance', 'bindings', function($scope, $modalInstance, bindings) {

        // a note about weekends:
        // ark-calendar sets hiddenDays to [0, 6] when weekends are false, want to replicate that model here
        var saturdayHidden;
        var sundayHidden;
        var checkboxLeft;
        var checkboxCenter;
        var checkboxRight;
        var ind;

        // Variables
        var settingsModalConfig = bindings.config.settingsModalConfig;
        if (!settingsModalConfig) {
          settingsModalConfig = {};
        }

        function grabConfigValue(key) {
          return settingsModalConfig[key];
        }

        $scope.weekDays = bindings.nameConfig.dayNames;
        $scope.modalTitle = grabConfigValue('modalTitle');
        $scope.allDayLabel = grabConfigValue('allDayLabel');
        $scope.popoversLabel = grabConfigValue('popoversLabel');
        $scope.onLabel = grabConfigValue('onLabel');
        $scope.offLabel = grabConfigValue('offLabel');
        $scope.checkboxLabel = grabConfigValue('checkboxLabel');
        $scope.timeIntervalLabel = grabConfigValue('timeIntervalLabel');
        $scope.firstDayLabel = grabConfigValue('firstDayLabel');
        $scope.daysToHideLabel = grabConfigValue('daysToHideLabel');
        $scope.closeButtonLabel = grabConfigValue('closeButtonLabel');
        $scope.saveButtonLabel = grabConfigValue('saveButtonLabel');
        $scope.noneOption = grabConfigValue('noneOption');
        $scope.errorLabel = grabConfigValue('errorLabel');
        $scope.errorMessage = grabConfigValue('errorMessage');

        $scope.days = true;
        $scope.time = bindings.config.slotDuration || '00:30:00';
        $scope.allDay = bindings.config.allDaySlot;
        $scope.tooltips = bindings.config.tooltips;
        $scope.genericCheckbox = bindings.config.genericCheckbox;
        $scope.hiddenDays = bindings.config.hiddenDays;
        $scope.weekends = bindings.config.weekends;

        $scope.error = '';
        $scope.slotDurations = ['00:15:00', '00:30:00', '00:60:00'];
        //$scope.hiddenDaysArr = bindings.hiddenDaysArr.slice() || [];
        $scope.hiddenDaysArr = [false, false, false, false, false, false, false];

        //check if generic checkbox is included in the header - to show/hide
        //the checkbox option in the template
        $scope.checkboxRendered = false;

        if (bindings.config.header) {
          checkboxLeft = bindings.config.header.left.search('checkbox') !== -1;
          checkboxCenter = bindings.config.header.center.search('checkbox') !== -1;
          checkboxRight = bindings.config.header.right.search('checkbox') !== -1;
        }

        if (checkboxLeft || checkboxCenter || checkboxRight) {
          $scope.checkboxRendered = true;
        }

        // the default is true - need to set for checkNone and changeFirstDay
        if (angular.isUndefined($scope.weekends)) {
          $scope.weekends = true;
        }

        if (angular.isUndefined($scope.allDay)) {
          $scope.allDay = true;
        }

        // setting initial values
        // make a copy of the hiddenDays array to keep track of the days checked by the user
        // copying array prevents changes from being applied until the user clicks ok or cancel
        if (angular.isUndefined($scope.hiddenDays)) {
          $scope.hiddenDays = [];
          $scope.daysChecked = [];
        } else {
          $scope.daysChecked = $scope.hiddenDays.slice();
        }

        // dayIndex determines which days are visible in firstDay dropdown
        if ($scope.weekends) { //weekend visible
          $scope.dayIndex = [0, 1, 2, 3, 4, 5, 6];
        } else {
          $scope.dayIndex = [1, 2, 3, 4, 5]; //do not include weekend
        }

        saturdayHidden = $scope.daysChecked.indexOf(6) !== -1; //saturday - 6
        sundayHidden = $scope.daysChecked.indexOf(0) !== -1; //sunday - 0

        //weekends are hidden, make sure days checked has saturday and sunday added
        if (!$scope.weekends) {
          if (!sundayHidden) {
            $scope.daysChecked.push(0);
          }
          if (!saturdayHidden) {
            $scope.daysChecked.push(6);
          }
          saturdayHidden = true;
          sundayHidden = true;
          $scope.daysChecked.sort();
        }

        if ($scope.daysChecked.length === 7) {
          $scope.error = $scope.errorMessage;
        }

        // if the day is hidden take out of the firstDay dayIndex
        for (var i = 0; i < $scope.daysChecked.length; ++i) {
          ind = $scope.dayIndex.indexOf($scope.daysChecked[i]);
          if (ind !== -1) {
            $scope.dayIndex.splice(ind, 1);
          }
          $scope.hiddenDaysArr[$scope.daysChecked[i]] = true;
        }
        // daysChecked has all the hidden days - if the firstDay is not configured or hidden - use the first day in the dayIndex
        $scope.firstDay = (angular.isUndefined(bindings.config.firstDay) || $scope.daysChecked.indexOf(bindings.config.firstDay) !== -1) ? $scope.dayIndex[0] : bindings.config.firstDay;

        $scope.changeTime = function(slot) {
          $scope.time = slot;
        };

        $scope.changeFirstDay = function(day) {
          $scope.firstDay = day;
        };

        // determine if None should be checked for HiddenDays option
        $scope.checkNone = function() {
          //weekends are false - daysChecked should have saturday and sunday hidden only
          if (!$scope.weekends) {
            return ($scope.daysChecked.length === 2 && saturdayHidden && sundayHidden);
          }
          // weekends are true - daysChecked should be empty
          else {
            return ($scope.daysChecked.length === 0);
          }
        };

        $scope.hideDay = function(day) {
          // update the daysChecked array and checkHash
          var index;
          index = $scope.daysChecked.indexOf(day);
          // if the day is not in the hiddenDays array then add it to hide the day
          if (index === -1) {
            $scope.daysChecked.push(day);
            $scope.daysChecked.sort();
            $scope.hiddenDaysArr[day] = true;
            // do not show this day in the first day dropdown
            $scope.dayIndex.splice($scope.dayIndex.indexOf(day), 1);
            $scope.firstDay = $scope.dayIndex[0];
          }
          // if the day is already in the hiddenDays array then remove it to show the day
          else {
            $scope.daysChecked.splice(index, 1);
            $scope.hiddenDaysArr[day] = false;
            if ($scope.dayIndex.indexOf(day) === -1) {
              $scope.dayIndex.push(day);
              $scope.dayIndex.sort();
              $scope.firstDay = $scope.dayIndex[0];
            }
          }
          // if all days have been hidden display an error message
          if ($scope.daysChecked.length === 7) {
            $scope.error = $scope.errorMessage;
          }
          // remove the error message if the user unchecks one of the days
          else {
            $scope.error = '';
          }
        };

        // if all days need to be shown reset the days, hiddenDaysArr, dayIndex and firstDay
        // reset the error in case there is one
        $scope.reset = function() {
          $scope.error = '';
          $scope.daysChecked = $scope.weekends ? [] : [0, 6];
          $scope.hiddenDaysArr = $scope.weekends ? [false, false, false, false, false, false, false] : [true, false, false, false, false, false, true];
          $scope.dayIndex = $scope.weekends ? [0, 1, 2, 3, 4, 5, 6] : [1, 2, 3, 4, 5];
          $scope.firstDay = $scope.dayIndex[0];
        };

        $scope.ok = function() {
          //display an error and do not allow submission of the form if user wants to hide all days
          if ($scope.daysChecked.length === 7) {
            $scope.error = $scope.errorMessage;
          } else {
            //reset the error message, if displayed and submit the values
            $scope.error = '';
            bindings.config.slotDuration = $scope.time;
            bindings.config.allDaySlot = $scope.allDay;
            bindings.config.tooltips = $scope.tooltips;
            bindings.config.firstDay = $scope.firstDay;
            bindings.config.genericCheckbox = $scope.genericCheckbox;
            bindings.config.hiddenDays = $scope.daysChecked;
            $scope.$close();
          }
        };

        $scope.cancel = function() {
          $scope.$dismiss('cancel');
        };
      }]);
})(angular);

angular.module('ark.calendar').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('templates/blockModal.html',
    "<div class=\"ark-calendar\"><div ng-show=\"error\" style=\"color:#EA4F6B\"><h3><span class=\"fonticon icon-alert-circle\"></span> {{error}}</h3></div><div ng-show=\"dateError\" style=\"color:#EA4F6B\"><h3><span class=\"fonticon icon-alert-circle\"></span> {{dateError}}</h3></div><span ng-click=\"cancel()\" class=\"icon-close close modal-dialog-close\"></span><div class=\"modal-header\"><h1 class=\"modal-title\">{{blockTitle}}</h1><div ng-if=\"displayTitle\"><label class=\"block-desc\">{{blockName}}</label><div class=\"block-text\"><input type=\"text\" class=\"form-control ng-pristine ng-valid\" placeholder=\"{{blockNamePlaceholder}}\" ng-model=\"title\" focus></div></div></div><div ng-if=\"displayDescription\"><label class=\"block-desc\">{{blockDescription}}</label><div class=\"block-text\"><textarea class=\"form-control ng-pristine ng-valid\" id=\"block-description\" ng-model=\"description\" placeholder=\"{{blockDescriptionPlaceholder}}\"></textarea></div></div><label class=\"block-desc\" ng-if=\"blockConfig\">{{blockType}}</label><div id=\"block-radios\"><label class=\"radio-inline\" ng-repeat=\"radioOption in blockConfig\"><input type=\"radio\" name=\"inlineRadioOptions\" ng-model=\"radioOptionsSelect.radioSelect\" ng-value=\"radioOption.id\"> {{radioOption.label}}</label></div><div ng-show=\"!generic && (configId === 1 || configId === 2)\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-model=\"isAnnual \"><span></span></label><span ng-click=\"isAnnual = !isAnnual;\" class=\"default-text\">{{isAnnualLabel}}</span></div><div ng-if=\"!generic && task === 'create'\"><h2>{{weeksSelectedLabel}}</h2><div class=\"single-week-div\" ng-repeat=\"week in weeks\"><label>{{week.weekLabel}}</label><div class=\"row\"><div ng-if=\"$index < 4\" ng-repeat=\"day in week.days\"><div ng-if=\"week.days[$index+4]\"><div class=\"datepickerbox col-md-6\" ng-click=\"week.days[$index].value = !week.days[$index].value; validateSelectedDates()\"><input type=\"checkbox\" class=\"ark-checkbox\" ng-model=\"week.days[$index].value\"><span></span> <span style=\"cursor: pointer\">{{week.days[$index].label}}</span></div><div class=\"datepickerbox col-md-6\" ng-click=\"week.days[$index+4].value = !week.days[$index+4].value; validateSelectedDates()\"><input type=\"checkbox\" class=\"ark-checkbox\" ng-model=\"week.days[$index+4].value\"><span></span> <span style=\"cursor: pointer\">{{week.days[$index+4].label}}</span></div></div><div ng-if=\"!week.days[$index+4]\"><div class=\"datepickerbox col-md-12\" ng-click=\"week.days[$index].value = !week.days[$index].value; validateSelectedDates()\"><input type=\"checkbox\" class=\"ark-checkbox\" ng-model=\"week.days[$index].value\"><span></span> <span style=\"cursor: pointer\">{{week.days[$index].label}}</span></div></div></div></div></div></div><div ng-if=\"generic && task === 'create'\"><h2>{{forDaysLabel}}</h2><div class=\"row\"><div ng-if=\"$index < 4\" ng-repeat=\"day in days\"><div ng-if=\"days[$index+4]\"><div class=\"datepickerbox col-md-6\" ng-click=\"days[$index].value = !days[$index].value; validateSelectedDates()\"><input type=\"checkbox\" class=\"ark-checkbox\" ng-model=\"days[$index].value\"><span></span> <span style=\"cursor: pointer\">{{days[$index].label}}</span></div><div class=\"datepickerbox col-md-6\" ng-click=\"days[$index+4].value = !days[$index+4].value; validateSelectedDates()\"><input type=\"checkbox\" class=\"ark-checkbox\" ng-model=\"days[$index+4].value\"><span></span> <span style=\"cursor: pointer\">{{days[$index+4].label}}</span></div></div><div ng-if=\"!days[$index+4]\"><div class=\"datepickerbox col-md-12\" ng-click=\"days[$index].value = !days[$index].value; validateSelectedDates()\"><input type=\"checkbox\" class=\"ark-checkbox\" ng-model=\"days[$index].value\"><span></span> <span style=\"cursor: pointer\">{{days[$index].label}}</span></div></div></div></div></div><hr><div ng-show=\"editable\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-model=\"allDayEvent\"><span></span></label><span ng-click=\"allDayEvent = !allDayEvent;\" class=\"default-text\">{{allDayEventLabel}}</span></div><div ng-if=\"!allDayEvent && (task === 'create' || task==='edit' && multiEvents)\"><label class=\"block-desc\">{{blockTimeSlot}}</label><div class=\"from-to-div row\"><div class=\"col-md-5\"><label id=\"block-from\">{{fromLabel}}</label><ark-time-picker ng-model=\"fromToTimes.fromTime\" widget-mode=\"false\"></ark-time-picker></div><div class=\"col-md-7\"><label id=\"block-from\">{{toLabel}}</label><ark-time-picker ng-model=\"fromToTimes.toTime\" widget-mode=\"false\"></ark-time-picker></div></div></div><div ng-if=\"task === 'edit' && !allDayEvent && !multiEvents\"><label class=\"block-desc\">{{blockTimeSlot}}</label><div class=\"from-to-div\"><label id=\"block-from\">{{fromLabel}}</label><div class=\"btn-group bootstrap-select from-to-day\"><button ark-select type=\"button\" class=\"btn btn-default dropdown-toggle selectpicker\" ng-model=\"fromToDays.fromDay\" ark-options=\"day.label as day.label for day in days\"></button></div><ark-time-picker ng-model=\"fromToTimes.fromTime\" widget-mode=\"false\"></ark-time-picker></div><div class=\"from-to-div\"><label id=\"block-to\">{{toLabel}}</label><div class=\"btn-group bootstrap-select from-to-day\"><button ark-select type=\"button\" class=\"btn btn-default dropdown-toggle selectpicker\" ng-model=\"fromToDays.toDay\" ark-options=\"day.label as day.label for day in days\"></button></div><ark-time-picker ng-model=\"fromToTimes.toTime\" widget-mode=\"false\"></ark-time-picker></div></div><div div class=\"modal-footer\"><button class=\"btn btn-default\" ng-click=\"cancel()\">{{cancelButtonLabel}}</button> <button ng-show=\"task === 'create'\" class=\"btn btn-primary pull-right\" ng-disabled=\"customErrorEventAllocate || dateError\" ng-click=\"create()\">{{createButtonLabel}}</button> <button ng-show=\"task === 'edit'\" class=\"btn btn-primary pull-right\" ng-disabled=\"customErrorEventAllocate\" ng-click=\"update()\">{{updateButtonLabel}}</button> <button ng-show=\"task === 'edit'\" class=\"btn btn-default pull-right\" ng-disabled=\"customErrorEventDelete\" ng-click=\"remove()\" style=\"margin-right: 10px\">{{deleteButtonLabel}}</button></div></div>"
  );


  $templateCache.put('templates/settingsTemplate.html',
    "<div><div ng-show=\"error\" style=\"color:#EA4F6B\"><h3><span class=\"fonticon icon-alert-circle\"></span> {{errorLabel}}: {{error}}</h3></div><span ng-click=\"cancel()\" class=\"icon-close close modal-dialog-close ng-scope\"></span><div class=\"modal-header ng-scope\"><h1 class=\"modal-title\">{{modalTitle}}</h1></div><div class=\"modal-body ng-scope\"><h2>{{allDayLabel}}</h2><div class=\"toggle-switch\"><input type=\"checkbox\" name=\"css-toggle-on-off-label\" class=\"toggle-switch-checkbox\" id=\"css-toggle-on-off-label\" ng-model=\"allDay\"><label class=\"toggle-switch-label\" for=\"css-toggle-on-off-label\"><span class=\"toggle-switch-inner\"></span> <span class=\"toggle-switch-switch\"></span></label><label for=\"css-toggle-on-off-label\" class=\"toggle-switch-label-text\"><span class=\"toggle-switch-on-label-text\">{{onLabel}}</span><span class=\"toggle-switch-off-label-text\">{{offLabel}}</span></label></div><h2>{{popoversLabel}}</h2><div class=\"toggle-switch\"><input type=\"checkbox\" name=\"css-toggle-on-off-label2\" class=\"toggle-switch-checkbox\" id=\"css-toggle-on-off-label2\" ng-model=\"tooltips\"><label class=\"toggle-switch-label\" for=\"css-toggle-on-off-label2\"><span class=\"toggle-switch-inner\"></span> <span class=\"toggle-switch-switch\"></span></label><label for=\"css-toggle-on-off-label\" class=\"toggle-switch-label-text\"><span class=\"toggle-switch-on-label-text\">{{onLabel}}</span><span class=\"toggle-switch-off-label-text\">{{offLabel}}</span></label></div><div ng-show=\"checkboxRendered\"><h2>{{checkboxLabel}}</h2><div class=\"toggle-switch\"><input type=\"checkbox\" name=\"css-toggle-on-off-label3\" class=\"toggle-switch-checkbox\" id=\"css-toggle-on-off-label3\" ng-model=\"genericCheckbox\"><label class=\"toggle-switch-label\" for=\"css-toggle-on-off-label3\"><span class=\"toggle-switch-inner\"></span> <span class=\"toggle-switch-switch\"></span></label><label for=\"css-toggle-on-off-label\" class=\"toggle-switch-label-text\"><span class=\"toggle-switch-on-label-text\">{{onLabel}}</span><span class=\"toggle-switch-off-label-text\">{{offLabel}}</span></label></div></div><h2>{{timeIntervalLabel}}</h2><div class=\"btn-group dropdown-group ark-dropdown dropdown\" is-open=\"timeIntervalDropdown.isopen\"><button type=\"button\" class=\"btn btn-default btn-dropdown ark-dropdown-toggle\">{{time}}<span class=\"icon-dropdown-arrow\"></span></button><ul class=\"dropdown-menu\" role=\"menu\"><li role=\"presentation\" ng-repeat=\"slot in slotDurations\" ng-click=\"changeTime(slot)\"><a role=\"menuitem\">{{slot}}</a></ul></div><h2>{{firstDayLabel}}</h2><div class=\"btn-group dropdown-group ark-dropdown dropdown\" is-open=\"firstDayDropdown.isopen\"><button type=\"button\" class=\"btn btn-default btn-dropdown ark-dropdown-toggle\">{{weekDays[firstDay] || noneOption}}<span class=\"icon-dropdown-arrow\"></span></button><ul class=\"dropdown-menu\" role=\"menu\"><li role=\"presentation\" ng-repeat=\"day in dayIndex\" ng-click=\"changeFirstDay(day)\"><a role=\"menuitem\">{{weekDays[day] || noneOption}}</a></ul></div><h2>{{daysToHideLabel}}</h2><div class=\"row\"><div class=\"col-md-6\"><div class=\"datepickerbox\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-click=\"reset()\" ng-checked=\"checkNone()\"><span></span></label><span class=\"default-text\">{{noneOption}}</span></div><div ng-show=\"weekends\" class=\"datepickerbox\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-click=\"hideDay(0)\" ng-checked=\"hiddenDaysArr[0]\"><span></span></label><span class=\"default-text\">{{weekDays[0]}}</span></div><div class=\"datepickerbox\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-click=\"hideDay(1)\" ng-checked=\"hiddenDaysArr[1]\"><span></span></label><span class=\"default-text\">{{weekDays[1]}}</span></div><div class=\"datepickerbox\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-click=\"hideDay(2)\" ng-checked=\"hiddenDaysArr[2]\"><span></span></label><span class=\"default-text\">{{weekDays[2]}}</span></div></div><div class=\"col-md-6\"><div class=\"datepickerbox\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-click=\"hideDay(3)\" ng-checked=\"hiddenDaysArr[3]\"><span></span></label><span class=\"default-text\">{{weekDays[3]}}</span></div><div class=\"datepickerbox\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-click=\"hideDay(4)\" ng-checked=\"hiddenDaysArr[4]\"><span></span></label><span class=\"default-text\">{{weekDays[4]}}</span></div><div class=\"datepickerbox\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-click=\"hideDay(5)\" ng-checked=\"hiddenDaysArr[5]\"><span></span></label><span class=\"default-text\">{{weekDays[5]}}</span></div><div ng-show=\"weekends\" class=\"datepickerbox\"><label><input type=\"checkbox\" class=\"ark-checkbox\" ng-click=\"hideDay(6)\" ng-checked=\"hiddenDaysArr[6]\"><span></span></label><span class=\"default-text\">{{weekDays[6]}}</span></div></div></div></div><!-- modal footer --><div class=\"modal-footer ng-scope\"><button ng-click=\"cancel()\" type=\"button\" class=\"btn btn-default\">{{closeButtonLabel}}</button> <button ng-click=\"ok()\" type=\"button\" class=\"btn btn-primary\">{{saveButtonLabel}}</button></div></div>"
  );

}]);
