text: 'use strict';
  (function(angular){
      'use strict';
  
      var Module = angular.module('datePicker', []);
  
      Module.constant('datePickerConfig', {
          template: 'templates/datepicker.html',
          view: 'month',
          views: ['year', 'month', 'date', 'hours', 'minutes'],
          step: 5
      });
  
      Module.filter('time',function () {
          function format(date){
              return ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2);
          }
  
          return function (date) {
              if (!(date instanceof Date)) {
                  date = new Date(date);
                  if (isNaN(date.getTime())) {
                      return undefined;
                  }
              }
              return format(date);
          };
      });
  
      function getVisibleMinutes(date, step) {
          date = new Date(date || new Date());
          date = new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours());
          var minutes = [];
          var stop = date.getTime() + 60 * 60 * 1000;
          while (date.getTime() < stop) {
              minutes.push(date);
              date = new Date(date.getTime() + step * 60 * 1000);
          }
          return minutes;
      }
  
      function getVisibleWeeks(date) {
          date = new Date(date || new Date());
          var startMonth = date.getMonth(), startYear = date.getYear();
          date.setDate(1);
          date.setHours(0);
          date.setMinutes(0);
          date.setSeconds(0);
          date.setMilliseconds(0);
  
          if (date.getDay() === 0) {
              date.setDate(-5);
          } else {
              date.setDate(date.getDate() - (date.getDay() - 1));
          }
          if (date.getDate() === 1) {
              date.setDate(-6);
          }
  
          var weeks = [];
          while (weeks.length < 6) {
              /*jshint -W116 */
              if(date.getYear()=== startYear && date.getMonth() > startMonth) break;
              var week = [];
              for (var i = 0; i < 7; i++) {
                  week.push(new Date(date));
                  date.setDate(date.getDate() + 1);
              }
              weeks.push(week);
          }
          return weeks;
      }
  
      function getVisibleYears(date) {
          var years = [];
          date = new Date(date || new Date());
          date.setFullYear(date.getFullYear() - (date.getFullYear() % 10));
          for (var i = 0; i < 12; i++) {
              years.push(new Date(date.getFullYear() + (i - 1), 0, 1));
          }
          return years;
      }
  
      function getDaysOfWeek(date) {
          date = new Date(date || new Date());
          date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
          date.setDate(date.getDate() - (date.getDay() - 1));
          var days = [];
          for (var i = 0; i < 7; i++) {
              days.push(new Date(date));
              date.setDate(date.getDate() + 1);
          }
          return days;
      }
  
      function getVisibleMonths(date) {
          date = new Date(date || new Date());
          var year = date.getFullYear();
          var months = [];
          for (var month = 0; month < 12; month++) {
              months.push(new Date(year, month, 1));
          }
          return months;
      }
  
      function getVisibleHours(date) {
          date = new Date(date || new Date());
          date.setHours(0);
          date.setMinutes(0);
          date.setSeconds(0);
          date.setMilliseconds(0);
          var hours = [];
          for (var i = 0; i < 24; i++) {
              hours.push(date);
              date = new Date(date.getTime() + 60 * 60 * 1000);
          }
          return hours;
      }
  
  
      function isAfter(model, date) {
          return model && model.getTime() <= date.getTime();
      }
  
      function isBefore(model, date) {
          return model.getTime() >= date.getTime();
      }
  
      function isSameYear(model, date) {
          return model && model.getFullYear() === date.getFullYear();
      }
  
      function isSameMonth(model, date) {
          return isSameYear(model, date) && model.getMonth() === date.getMonth();
      }
  
      function isSameDay(model, date) {
          return isSameMonth(model, date) && model.getDate() === date.getDate();
      }
  
      function isSameHour(model, date) {
          return isSameDay(model, date) && model.getHours() === date.getHours();
      }
  
      function isSameMinutes(model, date) {
          return isSameHour(model, date) && model.getMinutes() === date.getMinutes();
      }
  
  
  
      Module.directive('datePicker', ['datePickerConfig', function datePickerDirective(datePickerConfig) {
  
          //noinspection JSUnusedLocalSymbols
          return {
              // this is a bug ?
              template: '<div ng-include="template"></div>',
              scope: {
                  model: '=datePicker',
                  after: '=?',
                  before: '=?'
              },
              link: function (scope, element, attrs) {
  
                  scope.date = new Date(scope.model || new Date());
                  scope.views = datePickerConfig.views.concat();
                  scope.view = attrs.view || datePickerConfig.view;
                  scope.now = new Date();
                  scope.template = attrs.template || datePickerConfig.template;
  
                  var step = parseInt(attrs.step || datePickerConfig.step, 10);
                  var partial = !!attrs.partial;
  
                  /** @namespace attrs.minView, attrs.maxView */
                  scope.views =scope.views.slice(
                      scope.views.indexOf(attrs.maxView || 'year'),
                      scope.views.indexOf(attrs.minView || 'minutes')+1
                  );
  
                  if (scope.views.length === 1 || scope.views.indexOf(scope.view)===-1) {
                      scope.view = scope.views[0];
                  }
  
                  scope.setView = function (nextView) {
                      if (scope.views.indexOf(nextView) !== -1) {
                          scope.view = nextView;
                      }
                  };
  
                  scope.setDate = function (date) {
                      if(attrs.disabled) {
                          return;
                      }
                      scope.date = date;
                      // change next view
                      var nextView = scope.views[scope.views.indexOf(scope.view) + 1];
                      if ((!nextView || partial) || scope.model) {
  
                          scope.model = new Date(scope.model || date);
                          var view = partial ? 'minutes' : scope.view;
                          //noinspection FallThroughInSwitchStatementJS
                          switch (view) {
                              case 'minutes':
                                  scope.model.setMinutes(date.getMinutes());
                              /*falls through*/
                              case 'hours':
                                  scope.model.setHours(date.getHours());
                              /*falls through*/
                              case 'date':
                                  scope.model.setDate(date.getDate());
                              /*falls through*/
                              case 'month':
                                  scope.model.setMonth(date.getMonth());
                              /*falls through*/
                              case 'year':
                                  scope.model.setFullYear(date.getFullYear());
                          }
                          scope.$emit('setDate', scope.model, scope.view);
                      }
  
                      if (nextView) {
                          scope.setView(nextView);
                      }
                  };
  
                  function update() {
                      var view = scope.view;
                      var date = scope.date;
                      switch (view) {
                          case 'year':
                              scope.years = getVisibleYears(date);
                              break;
                          case 'month':
                              scope.months = getVisibleMonths(date);
                              break;
                          case 'date':
                              scope.weekdays = scope.weekdays || getDaysOfWeek();
                              scope.weeks = getVisibleWeeks(date);
                              break;
                          case 'hours':
                              scope.hours = getVisibleHours(date);
                              break;
                          case 'minutes':
                              scope.minutes = getVisibleMinutes(date, step);
                              break;
                      }
                  }
  
                  function watch() {
                      if (scope.view !== 'date') {
                          return scope.view;
                      }
                      return scope.model ? scope.model.getMonth() : null;
                  }
  
  
                  scope.$watch(watch, update);
  
                  scope.next = function (delta) {
                      var date = scope.date;
                      delta = delta || 1;
                      switch (scope.view) {
                          case 'year':
                          /*falls through*/
                          case 'month':
                              date.setFullYear(date.getFullYear() + delta);
                              break;
                          case 'date':
                              date.setMonth(date.getMonth() + delta);
                              break;
                          case 'hours':
                          /*falls through*/
                          case 'minutes':
                              date.setHours(date.getHours() + delta);
                              break;
                      }
                      update();
                  };
  
                  scope.prev = function (delta) {
                      return scope.next(-delta || -1);
                  };
  
                  scope.isAfter = function (date) {
                      return scope.after && isAfter(date, scope.after);
                  };
  
                  scope.isBefore = function (date) {
                      return scope.before && isBefore(date, scope.before);
                  };
  
                  scope.isSameMonth = function (date) {
                      return isSameMonth(scope.model, date);
                  };
  
                  scope.isSameYear = function (date) {
                      return isSameYear(scope.model, date);
                  };
  
                  scope.isSameDay = function (date) {
                      return isSameDay(scope.model, date);
                  };
  
                  scope.isSameHour = function (date) {
                      return isSameHour(scope.model, date);
                  };
  
                  scope.isSameMinutes = function (date) {
                      return isSameMinutes(scope.model, date);
                  };
  
                  scope.isNow = function (date) {
                      var is = true;
                      var now = scope.now;
                      //noinspection FallThroughInSwitchStatementJS
                      switch (scope.view) {
                          case 'minutes':
                              is &= ~~(date.getMinutes()/step) === ~~(now.getMinutes()/step);
                          /*falls through*/
                          case 'hours':
                              is &= date.getHours() === now.getHours();
                          /*falls through*/
                          case 'date':
                              is &= date.getDate() === now.getDate();
                          /*falls through*/
                          case 'month':
                              is &= date.getMonth() === now.getMonth();
                          /*falls through*/
                          case 'year':
                              is &= date.getFullYear() === now.getFullYear();
                      }
                      return is;
                  };
              }
          };
      }]);
  
      'use strict';
  
      var Module = angular.module('datePicker');
  
      Module.directive('dateRange', function () {
          return {
              templateUrl: 'templates/daterange.html',
              scope: {
                  start: '=',
                  end: '='
              },
              link: function (scope, element, attrs) {
                  attrs.$observe('disabled', function(isDisabled){
                      scope.disableDatePickers = !!isDisabled;
                  });
                  scope.$watch('start.getTime()', function (value) {
                      if (value && scope.end && value > scope.end.getTime()) {
                          scope.end = new Date(value);
                      }
                  });
                  scope.$watch('end.getTime()', function (value) {
                      if (value && scope.start && value < scope.start.getTime()) {
                          scope.start = new Date(value);
                      }
                  });
              }
          };
      });
  
      'use strict';
  
      var PRISTINE_CLASS = 'ng-pristine',
          DIRTY_CLASS = 'ng-dirty';
  
      var Module = angular.module('datePicker');
  
      Module.constant('dateTimeConfig', {
          template: function (attrs) {
              return '' +
                  '<div ' +
                  'date-picker="' + attrs.ngModel + '" ' +
                  (attrs.view ? 'view="' + attrs.view + '" ' : '') +
                  (attrs.maxView ? 'max-view="' + attrs.maxView + '" ' : '') +
                  (attrs.template ? 'template="' + attrs.template + '" ' : '') +
                  (attrs.minView ? 'min-view="' + attrs.minView + '" ' : '') +
                  (attrs.partial ? 'partial="' + attrs.partial + '" ' : '') +
                  'class="dropdown-menu"></div>';
          },
          format: 'yyyy-MM-dd HH:mm',
          views: ['date', 'year', 'month', 'hours', 'minutes'],
          dismiss: false,
          position: 'relative'
      });
  
      Module.directive('dateTimeAppend', function () {
          return {
              link: function (scope, element) {
                  element.bind('click', function () {
                      element.find('input')[0].focus();
                  });
              }
          };
      });
  
      Module.directive('dateTime', ['$compile', '$document', '$filter', 'dateTimeConfig', '$parse', function ($compile, $document, $filter, dateTimeConfig, $parse) {
          var body = $document.find('body');
          var dateFilter = $filter('date');
  
          return {
              require: 'ngModel',
              scope:true,
              link: function (scope, element, attrs, ngModel) {
                  var format = attrs.format || dateTimeConfig.format;
                  var parentForm = element.inheritedData('$formController');
                  var views = $parse(attrs.views)(scope) || dateTimeConfig.views.concat();
                  var view = attrs.view || views[0];
                  var index = views.indexOf(view);
                  var dismiss = attrs.dismiss ? $parse(attrs.dismiss)(scope) : dateTimeConfig.dismiss;
                  var picker = null;
                  var position = attrs.position || dateTimeConfig.position;
                  var container = null;
  
                  if (index === -1) {
                      views.splice(index, 1);
                  }
  
                  views.unshift(view);
  
  
                  function formatter(value) {
                      return dateFilter(value, format);
                  }
  
                  function parser() {
                      return ngModel.$modelValue;
                  }
  
                  ngModel.$formatters.push(formatter);
                  ngModel.$parsers.unshift(parser);
  
  
                  var template = dateTimeConfig.template(attrs);
  
                  function updateInput(event) {
                      event.stopPropagation();
                      if (ngModel.$pristine) {
                          ngModel.$dirty = true;
                          ngModel.$pristine = false;
                          element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);
                          if (parentForm) {
                              parentForm.$setDirty();
                          }
                          ngModel.$render();
                      }
                  }
  
                  function clear() {
                      if (picker) {
                          picker.remove();
                          picker = null;
                      }
                      if (container) {
                          container.remove();
                          container = null;
                      }
                  }
  
                  function showPicker() {
                      if (picker) {
                          return;
                      }
                      // create picker element
                      picker = $compile(template)(scope);
                      scope.$digest();
  
                      scope.$on('setDate', function (event, date, view) {
                          updateInput(event);
                          if (dismiss && views[views.length - 1] === view) {
                              clear();
                          }
                      });
  
                      scope.$on('$destroy', clear);
  
                      // move picker below input element
  
                      if (position === 'absolute') {
                          var pos = angular.extend(element.offset(), { height: element[0].offsetHeight });
                          picker.css({ top: pos.top + pos.height, left: pos.left, display: 'block', position: position});
                          body.append(picker);
                      } else {
                          // relative
                          container = angular.element('<div date-picker-wrapper></div>');
                          element[0].parentElement.insertBefore(container[0], element[0]);
                          container.append(picker);
  //          this approach doesn't work
  //          element.before(picker);
                          picker.css({top: element[0].offsetHeight + 'px', display: 'block'});
                      }
  
                      picker.bind('mousedown', function (evt) {
                          evt.preventDefault();
                      });
                  }
  
                  element.bind('focus', showPicker);
                  element.bind('blur', clear);
              }
          };
      }]);
  
      angular.module("datePicker").run(["$templateCache", function($templateCache) {
  
          $templateCache.put("templates/datepicker.html",
              "<div ng-switch=\"view\">\r" +
                  "\n" +
                  "  <div ng-switch-when=\"date\">\r" +
                  "\n" +
                  "    <table>\r" +
                  "\n" +
                  "      <thead>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <th ng-click=\"prev()\">‹</th>\r" +
                  "\n" +
                  "        <th colspan=\"5\" class=\"switch\" ng-click=\"setView('month')\">{{date|date:\"yyyy MMMM\"}}</th>\r" +
                  "\n" +
                  "        <th ng-click=\"next()\">›</i></th>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <th ng-repeat=\"day in weekdays\" style=\"overflow: hidden\">{{ day|date:\"EEE\" }}</th>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </thead>\r" +
                  "\n" +
                  "      <tbody>\r" +
                  "\n" +
                  "      <tr ng-repeat=\"week in weeks\">\r" +
                  "\n" +
                  "        <td ng-repeat=\"day in week\">\r" +
                  "\n" +
                  "          <span\r" +
                  "\n" +
                  "            ng-class=\"{'now':isNow(day),'active':isSameDay(day),'disabled':(day.getMonth()!=date.getMonth()),'after':isAfter(day),'before':isBefore(day)}\"\r" +
                  "\n" +
                  "            ng-click=\"setDate(day)\" ng-bind=\"day.getDate()\"></span>\r" +
                  "\n" +
                  "        </td>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </tbody>\r" +
                  "\n" +
                  "    </table>\r" +
                  "\n" +
                  "  </div>\r" +
                  "\n" +
                  "  <div ng-switch-when=\"year\">\r" +
                  "\n" +
                  "    <table>\r" +
                  "\n" +
                  "      <thead>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <th ng-click=\"prev(10)\">‹</th>\r" +
                  "\n" +
                  "        <th colspan=\"5\" class=\"switch\">{{years[0].getFullYear()}}-{{years[years.length-1].getFullYear()}}</th>\r" +
                  "\n" +
                  "        <th ng-click=\"next(10)\">›</i></th>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </thead>\r" +
                  "\n" +
                  "      <tbody>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <td colspan=\"7\">\r" +
                  "\n" +
                  "          <span ng-class=\"{'active':isSameYear(year),'now':isNow(year)}\"\r" +
                  "\n" +
                  "                ng-repeat=\"year in years\"\r" +
                  "\n" +
                  "                ng-click=\"setDate(year)\" ng-bind=\"year.getFullYear()\"></span>\r" +
                  "\n" +
                  "        </td>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </tbody>\r" +
                  "\n" +
                  "    </table>\r" +
                  "\n" +
                  "  </div>\r" +
                  "\n" +
                  "  <div ng-switch-when=\"month\">\r" +
                  "\n" +
                  "    <table>\r" +
                  "\n" +
                  "      <thead>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <th ng-click=\"prev()\">‹</th>\r" +
                  "\n" +
                  "        <th colspan=\"5\" class=\"switch\" ng-click=\"setView('year')\">{{ date|date:\"yyyy\" }}</th>\r" +
                  "\n" +
                  "        <th ng-click=\"next()\">›</i></th>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </thead>\r" +
                  "\n" +
                  "      <tbody>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <td colspan=\"7\">\r" +
                  "\n" +
                  "          <span ng-repeat=\"month in months\"\r" +
                  "\n" +
                  "                ng-class=\"{'active':isSameMonth(month),'after':isAfter(month),'before':isBefore(month),'now':isNow(month)}\"\r" +
                  "\n" +
                  "                ng-click=\"setDate(month)\"\r" +
                  "\n" +
                  "                ng-bind=\"month|date:'MMM'\"></span>\r" +
                  "\n" +
                  "        </td>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </tbody>\r" +
                  "\n" +
                  "    </table>\r" +
                  "\n" +
                  "  </div>\r" +
                  "\n" +
                  "  <div ng-switch-when=\"hours\">\r" +
                  "\n" +
                  "    <table>\r" +
                  "\n" +
                  "      <thead>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <th ng-click=\"prev(24)\">‹</th>\r" +
                  "\n" +
                  "        <th colspan=\"5\" class=\"switch\" ng-click=\"setView('date')\">{{ date|date:\"dd MMMM yyyy\" }}</th>\r" +
                  "\n" +
                  "        <th ng-click=\"next(24)\">›</i></th>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </thead>\r" +
                  "\n" +
                  "      <tbody>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <td colspan=\"7\">\r" +
                  "\n" +
                  "          <span ng-repeat=\"hour in hours\"\r" +
                  "\n" +
                  "                ng-class=\"{'now':isNow(hour),'active':isSameHour(hour)}\"\r" +
                  "\n" +
                  "                ng-click=\"setDate(hour)\" ng-bind=\"hour|time\"></span>\r" +
                  "\n" +
                  "        </td>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </tbody>\r" +
                  "\n" +
                  "    </table>\r" +
                  "\n" +
                  "  </div>\r" +
                  "\n" +
                  "  <div ng-switch-when=\"minutes\">\r" +
                  "\n" +
                  "    <table>\r" +
                  "\n" +
                  "      <thead>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <th ng-click=\"prev()\">‹</th>\r" +
                  "\n" +
                  "        <th colspan=\"5\" class=\"switch\" ng-click=\"setView('hours')\">{{ date|date:\"dd MMMM yyyy\" }}\r" +
                  "\n" +
                  "        </th>\r" +
                  "\n" +
                  "        <th ng-click=\"next()\">›</i></th>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </thead>\r" +
                  "\n" +
                  "      <tbody>\r" +
                  "\n" +
                  "      <tr>\r" +
                  "\n" +
                  "        <td colspan=\"7\">\r" +
                  "\n" +
                  "          <span ng-repeat=\"minute in minutes\"\r" +
                  "\n" +
                  "                ng-class=\"{active:isSameMinutes(minute),'now':isNow(minute)}\"\r" +
                  "\n" +
                  "                ng-click=\"setDate(minute)\"\r" +
                  "\n" +
                  "                ng-bind=\"minute|time\"></span>\r" +
                  "\n" +
                  "        </td>\r" +
                  "\n" +
                  "      </tr>\r" +
                  "\n" +
                  "      </tbody>\r" +
                  "\n" +
                  "    </table>\r" +
                  "\n" +
                  "  </div>\r" +
                  "\n" +
                  "</div>\r" +
                  "\n"
          );
  
          $templateCache.put("templates/daterange.html",
              "<div>\r" +
                  "\n" +
                  "    <table>\r" +
                  "\n" +
                  "        <tr>\r" +
                  "\n" +
                  "            <td valign=\"top\">\r" +
                  "\n" +
                  "                <div date-picker=\"start\" ng-disabled=\"disableDatePickers\"  class=\"date-picker\" date after=\"start\" before=\"end\" min-view=\"date\" max-view=\"date\"></div>\r" +
                  "\n" +
                  "            </td>\r" +
                  "\n" +
                  "            <td valign=\"top\">\r" +
                  "\n" +
                  "                <div date-picker=\"end\" ng-disabled=\"disableDatePickers\"  class=\"date-picker\" date after=\"start\" before=\"end\"  min-view=\"date\" max-view=\"date\"></div>\r" +
                  "\n" +
                  "            </td>\r" +
                  "\n" +
                  "        </tr>\r" +
                  "\n" +
                  "    </table>\r" +
                  "\n" +
                  "</div>\r" +
                  "\n"
          );
  
      }]);
  })(angular);