/*
 * Copyright (c) 2010-2019 BSI Business Systems Integration AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BSI Business Systems Integration AG - initial API and implementation
 */
import {CalendarComponent, CalendarLayout, CalendarListComponent, DateRange, dates, GroupBox, HtmlComponent, KeyStrokeContext, menus, objects, scout, scrollbars, strings, Widget} from '../index';
import $ from 'jquery';

export default class Calendar extends Widget {

  constructor() {
    super();

    this.monthViewNumberOfWeeks = 6;
    this.numberOfHourDivisions = this.getConfiguredNumberOfHourDivisions();
    this.heightPerDivision = this.getConfiguredHeightPerDivision();
    this.startHour = this.getConfiguredStartHour();
    this.heightPerHour = this.numberOfHourDivisions * this.heightPerDivision;
    this.heightPerDay = 24 * this.heightPerHour;
    this.spaceBeforeScrollTop = 15;
    this.workDayIndices = [1, 2, 3, 4, 5]; // Workdays: Mon-Fri (Week starts at Sun in JS)
    this.components = [];
    this.displayMode;
    this.displayCondensed = false;
    this.loadInProgress = false;
    this.selectedDate = null;
    this.showDisplayModeSelection = true;
    this.title = null;
    this.useOverflowCells = true;
    this.viewRange = null;
    this.calendarToggleListWidth = 270;
    this.calendarToggleYearWidth = 215;

    // main elements
    this.$container = null;
    this.$header = null;
    this.$range = null;
    this.$commands = null;
    this.$grids = null;
    this.$grid = null;
    this.$topGrid = null;
    this.$list = null;
    this.$progress = null;

    // additional modes; should be stored in model
    this._showYearPanel = false;
    this._showListPanel = false;

    /**
     * The narrow view range is different from the regular view range.
     * It contains only dates that exactly match the requested dates,
     * the regular view range contains also dates from the first and
     * next month. The exact range is not sent to the server.
     */
    this._exactRange = null;

    /**
     * When the list panel is shown, this list contains the scout.CalenderListComponent
     * items visible on the list.
     */
    this._listComponents = [];
    this.menuInjectionTarget = null;
    this._menuInjectionTargetMenusChangedHandler = null;

    this._addWidgetProperties(['components', 'menus', 'selectedComponent']);
  }

  init(model, session, register) {
    super.init(model, session, register);
  }

  /**
   * Enum providing display-modes for calender-like components like calendar and planner.
   * @see ICalendarDisplayMode.java
   */
  static DisplayMode = {
    DAY: 1,
    WEEK: 2,
    MONTH: 3,
    WORK_WEEK: 4
  };

  /**
   * Used as a multiplier in date calculations back- and forward (in time).
   */
  static Direction = {
    BACKWARD: -1,
    FORWARD: 1
  };

  getConfiguredNumberOfHourDivisions() {
    return 2;
  }

  getConfiguredHeightPerDivision() {
    return 30;
  }

  getConfiguredStartHour() {
    return 6;
  }

  _isDay() {
    return this.displayMode === Calendar.DisplayMode.DAY;
  }

  _isWeek() {
    return this.displayMode === Calendar.DisplayMode.WEEK;
  }

  _isMonth() {
    return this.displayMode === Calendar.DisplayMode.MONTH;
  }

  _isWorkWeek() {
    return this.displayMode === Calendar.DisplayMode.WORK_WEEK;
  }

  /**
   * @override
   */
  _createKeyStrokeContext() {
    return new KeyStrokeContext();
  }

  _init(model) {
    super._init(model);
    this._yearPanel = scout.create('YearPanel', {
      parent: this
    });
    this._yearPanel.on('dateSelect', this._onYearPanelDateSelect.bind(this));
    this.modesMenu = scout.create('CalendarModesMenu', {
      parent: this,
      visible: false,
      displayMode: this.displayMode
    });
    this._setSelectedDate(model.selectedDate);
    this._setDisplayMode(model.displayMode);
    this._setMenuInjectionTarget(model.menuInjectionTarget);
    this._exactRange = this._calcExactRange();
    this._yearPanel.setViewRange(this._exactRange);
    this.viewRange = this._calcViewRange();
  }

  setSelectedDate(date) {
    this.setProperty('selectedDate', date);
  }

  _setSelectedDate(date) {
    date = dates.ensure(date);
    this._setProperty('selectedDate', date);
    this._yearPanel.selectDate(this.selectedDate);
  }

  setDisplayMode(displayMode) {
    if (objects.equals(this.displayMode, displayMode)) {
      return;
    }
    var oldDisplayMode = this.displayMode;
    this._setDisplayMode(displayMode);
    if (this.rendered) {
      this._renderDisplayMode(oldDisplayMode);
    }
  }

  _setDisplayMode(displayMode) {
    this._setProperty('displayMode', displayMode);
    this._yearPanel.setDisplayMode(this.displayMode);
    this.modesMenu.setDisplayMode(displayMode);
    if (this._isWorkWeek()) {
      // change date if selectedDate is on a weekend
      var p = this._dateParts(this.selectedDate, true);
      if (p.day > 4) {
        this.setSelectedDate(new Date(p.year, p.month, p.date - p.day + 4));
      }
    }
  }

  _renderDisplayMode(oldDisplayMode) {
    if (this.rendering) {
      // only do it on property changes
      return;
    }
    this._updateModel(false, true);

    // only render if components have another layout
    if (oldDisplayMode === Calendar.DisplayMode.MONTH || this.displayMode === Calendar.DisplayMode.MONTH) {
      this._renderComponents();
      this.needsScrollToStartHour = true;
    }
  }

  _setViewRange(viewRange) {
    viewRange = DateRange.ensure(viewRange);
    this._setProperty('viewRange', viewRange);
  }

  _setMenus(menus) {
    if (this._checkMenuInjectionTarget(this.menuInjectionTarget)) {
      var originalMenus = this._removeInjectedMenus(this.menuInjectionTarget, this.menus);
      this.menuInjectionTarget.setMenus(menus.concat(originalMenus));
    }
    this._setProperty('menus', menus);
  }

  _setMenuInjectionTarget(menuInjectionTarget) {
    if (objects.isString(menuInjectionTarget)) {
      menuInjectionTarget = scout.widget(menuInjectionTarget);
    }
    // Remove injected menus and installed listener from old injection target
    if (this._checkMenuInjectionTarget(this.menuInjectionTarget)) {
      menuInjectionTarget.off('propertyChange:menus', this._menuInjectionTargetMenusChangedHandler);
      var originalMenus = this._removeInjectedMenus(this.menuInjectionTarget, this.menus);
      this.menuInjectionTarget.setMenus(originalMenus);
    }
    if (this._checkMenuInjectionTarget(menuInjectionTarget)) {
      menuInjectionTarget.setMenus(this.menus.concat(menuInjectionTarget.menus));
      // Listen for menu changes on the injection target. Re inject menus into target if the menus have been altered.
      this._menuInjectionTargetMenusChangedHandler = menuInjectionTarget.on('propertyChange:menus',
        function(evt) {
          if (this.menuInjectionTarget.menus.some(function(element) {
            return this.menus.includes(element);
          }.bind(this))) {
            // Menus have already been injected => Do nothing
            return;
          }
          this.menuInjectionTarget.setMenus(this.menus.concat(this.menuInjectionTarget.menus));
        }.bind(this)
      );
    }
    this._setProperty('menuInjectionTarget', menuInjectionTarget);
  }

  _checkMenuInjectionTarget(menuInjectionTarget) {
    return menuInjectionTarget instanceof GroupBox;
  }

  _removeInjectedMenus(menuInjectionTarget, injectedMenus) {
    return menuInjectionTarget.menus.filter(function(element) {
      return !injectedMenus.includes(element);
    });
  }

  _render() {
    this.$container = this.$parent.appendDiv('calendar');

    var layout = new CalendarLayout(this);
    this.htmlComp = HtmlComponent.install(this.$container, this.session);
    this.htmlComp.setLayout(layout);

    // main elements
    this.$header = this.$container.appendDiv('calendar-header');
    this.$headerRow1 = this.$header.appendDiv('calendar-header-row first');
    this.$headerRow2 = this.$header.appendDiv('calendar-header-row last');
    this._yearPanel.render();

    this.$grids = this.$container.appendDiv('calendar-grids');
    this.$topGrid = this.$grids.appendDiv('calendar-top-grid');
    this.$grid = this.$grids.appendDiv('calendar-grid');

    this.$list = this.$container.appendDiv('calendar-list-container').appendDiv('calendar-list');
    this.$listTitle = this.$list.appendDiv('calendar-list-title');

    // header contains range, title and commands. On small screens title will be moved to headerRow2
    this.$range = this.$headerRow1.appendDiv('calendar-range');
    this.$range.appendDiv('calendar-previous').click(this._onPreviousClick.bind(this));
    this.$range.appendDiv('calendar-today', this.session.text('ui.CalendarToday')).click(this._onTodayClick.bind(this));
    this.$range.appendDiv('calendar-next').click(this._onNextClick.bind(this));

    // title
    this.$title = this.$headerRow1.appendDiv('calendar-title');
    this.$select = this.$title.appendDiv('calendar-select');
    this.$progress = this.$title.appendDiv('busyindicator-label');

    // commands
    this.$commands = this.$headerRow1.appendDiv('calendar-commands');
    this.$commands.appendDiv('calendar-mode first', this.session.text('ui.CalendarDay')).attr('data-mode', Calendar.DisplayMode.DAY).click(this._onDisplayModeClick.bind(this));
    this.$commands.appendDiv('calendar-mode', this.session.text('ui.CalendarWorkWeek')).attr('data-mode', Calendar.DisplayMode.WORK_WEEK).click(this._onDisplayModeClick.bind(this));
    this.$commands.appendDiv('calendar-mode', this.session.text('ui.CalendarWeek')).attr('data-mode', Calendar.DisplayMode.WEEK).click(this._onDisplayModeClick.bind(this));
    this.$commands.appendDiv('calendar-mode last', this.session.text('ui.CalendarMonth')).attr('data-mode', Calendar.DisplayMode.MONTH).click(this._onDisplayModeClick.bind(this));
    this.modesMenu.render(this.$commands);
    this.$commands.appendDiv('calendar-toggle-year').click(this._onYearClick.bind(this));
    this.$commands.appendDiv('calendar-toggle-list').click(this._onListClick.bind(this));

    // Append the top grid (day/week views)
    var $weekHeader = this.$topGrid.appendDiv('calendar-week-header');
    $weekHeader.appendDiv('calendar-week-name');
    for (var dayTop = 0; dayTop < 7; dayTop++) {
      $weekHeader.appendDiv('calendar-day-name')
        .data('day', dayTop);
    }

    this.$topGrid.appendDiv('calendar-week-task').attr('data-axis-name', this.session.text('ui.CalendarDay'));
    var $weekTopGridDays = this.$topGrid.appendDiv('calendar-week-allday-container');
    $weekTopGridDays.appendDiv('calendar-week-name');

    var dayContextMenuCallback = this._onDayContextMenu.bind(this);
    for (var dayBottom = 0; dayBottom < 7; dayBottom++) {
      $weekTopGridDays.appendDiv('calendar-day')
        .addClass('calendar-scrollable-components')
        .data('day', dayBottom)
        .on('contextmenu', dayContextMenuCallback);
    }

    for (var w = 1; w < 7; w++) {
      var $w = this.$grid.appendDiv('calendar-week');
      for (var d = 0; d < 8; d++) {
        var $d = $w.appendDiv();
        if (w > 0 && d === 0) {
          $d.addClass('calendar-week-name');
        } else if (w > 0 && d > 0) {
          $d.addClass('calendar-day')
            .data('day', d)
            .data('week', w)
            .on('contextmenu', dayContextMenuCallback);
        }
      }
    }

    // click event on all day and children elements
    var mousedownCallbackWithTime = this._onDayMouseDown.bind(this, true);
    this.$grid.find('.calendar-day').on('mousedown', mousedownCallbackWithTime);
    var mousedownCallback = this._onDayMouseDown.bind(this, false);
    this.$topGrid.find('.calendar-day').on('mousedown', mousedownCallback);

    this._updateScreen(false, false);
  }

  _renderProperties() {
    super._renderProperties();
    this._renderComponents();
    this._renderSelectedComponent();
    this._renderLoadInProgress();
    this._renderDisplayMode();
  }

  _renderComponents() {
    this.components.sort(this._sortFromTo);
    this.components.forEach(component => component.remove());
    this.components.forEach(component => component.render());
    this._arrangeComponents();
    this._updateListPanel();
  }

  _renderSelectedComponent() {
    if (this.selectedComponent) {
      this.selectedComponent.setSelected(true);
    }
  }

  _renderLoadInProgress() {
    this.$progress.setVisible(this.loadInProgress);
  }

  updateScrollPosition(animate) {
    if (!this.rendered) {
      // Execute delayed because table may be not layouted yet
      this.session.layoutValidator.schedulePostValidateFunction(this._updateScrollPosition.bind(this, true, animate));
    } else {
      this._updateScrollPosition(true, animate);
    }
  }

  _updateScrollPosition(scrollToInitialTime, animate) {
    if (this._isMonth()) {
      this._scrollToSelectedComponent(animate);
    } else {
      if (this.selectedComponent) {
        if (this.selectedComponent.fullDay) {
          this._scrollToSelectedComponent(animate); // scroll top-grid to selected component
          if (scrollToInitialTime) {
            this._scrollToInitialTime(animate); // scroll grid to initial time
          }
        } else {
          var date = dates.parseJsonDate(this.selectedComponent.fromDate, this.selectedComponent);
          var topPercent = this._dayPosition(date.getHours(), date.getMinutes()) / 100;
          var topPos = this.heightPerDay * topPercent;
          scrollbars.scrollTop(this.$grid, topPos - this.spaceBeforeScrollTop, {
            animate: animate
          });
        }
      } else if (scrollToInitialTime) {
        this._scrollToInitialTime(animate);
      }
    }
  }

  _scrollToSelectedComponent(animate) {
    if (this.selectedComponent && this.selectedComponent._$parts[0] && this.selectedComponent._$parts[0].parent() && this.selectedComponent._$parts[0].isVisible()) {
      scrollbars.scrollTo(this.selectedComponent._$parts[0].parent(), this.selectedComponent._$parts[0], {
        animate: animate
      });
    }
  }

  _scrollToInitialTime(animate) {
    this.needsScrollToStartHour = false;
    if (!this._isMonth()) {
      if (this.selectedComponent && !this.selectedComponent.fullDay) {
        var date = dates.parseJsonDate(this.selectedComponent.fromDate);
        var topPercent = this._dayPosition(date.getHours(), date.getMinutes()) / 100;
        var topPos = this.heightPerDay * topPercent;
        scrollbars.scrollTop(this.$grid, topPos - this.spaceBeforeScrollTop, {
          animate: animate
        });
      } else {
        var scrollTargetTop = this.heightPerHour * this.startHour;
        scrollbars.scrollTop(this.$grid, scrollTargetTop - this.spaceBeforeScrollTop, {
          animate: animate
        });
      }
    }
  }

  /* -- basics, events -------------------------------------------- */

  _onPreviousClick(event) {
    this._navigateDate(Calendar.Direction.BACKWARD);
  }

  _onNextClick(event) {
    this._navigateDate(Calendar.Direction.FORWARD);
  }

  _dateParts(date, modulo) {
    var parts = {
      year: date.getFullYear(),
      month: date.getMonth(),
      date: date.getDate(),
      day: date.getDay()
    };
    if (modulo) {
      parts.day = (date.getDay() + 6) % 7;
    }
    return parts;
  }

  _navigateDate(direction) {
    this.selectedDate = this._calcSelectedDate(direction);
    this._updateModel(true, false);
  }

  _calcSelectedDate(direction) {
    var p = this._dateParts(this.selectedDate),
      dayOperand = direction,
      weekOperand = direction * 7,
      monthOperand = direction;

    if (this._isDay()) {
      return new Date(p.year, p.month, p.date + dayOperand);
    } else if (this._isWeek() || this._isWorkWeek()) {
      return new Date(p.year, p.month, p.date + weekOperand);
    } else if (this._isMonth()) {
      return dates.shift(this.selectedDate, 0, monthOperand, 0);
    }
  }

  _updateModel(updateTopGrid, animate) {
    this._exactRange = this._calcExactRange();
    this._yearPanel.setViewRange(this._exactRange);
    this.viewRange = this._calcViewRange();
    this.trigger('modelChange');
    this._updateScreen(updateTopGrid, animate);
  }

  /**
   * Calculates exact date range of displayed components based on selected-date.
   */
  _calcExactRange() {
    var from, to,
      p = this._dateParts(this.selectedDate, true);

    if (this._isDay()) {
      from = new Date(p.year, p.month, p.date);
      to = new Date(p.year, p.month, p.date + 1);
    } else if (this._isWeek()) {
      from = new Date(p.year, p.month, p.date - p.day);
      to = new Date(p.year, p.month, p.date - p.day + 6);
    } else if (this._isMonth()) {
      from = new Date(p.year, p.month, 1);
      to = new Date(p.year, p.month + 1, 0);
    } else if (this._isWorkWeek()) {
      from = new Date(p.year, p.month, p.date - p.day);
      to = new Date(p.year, p.month, p.date - p.day + 4);
    } else {
      throw new Error('invalid value for displayMode');
    }

    return new DateRange(from, to);
  }

  /**
   * Calculates the view-range, which is what the user sees in the UI.
   * The view-range is wider than the exact-range in the monthly mode,
   * as it contains also dates from the previous and next month.
   */
  _calcViewRange() {
    var viewFrom = calcViewFromDate(this._exactRange.from),
      viewTo = calcViewToDate(viewFrom);
    return new DateRange(viewFrom, viewTo);

    function calcViewFromDate(fromDate) {
      var i, tmpDate = new Date(fromDate.valueOf());
      for (i = 0; i < 42; i++) {
        tmpDate.setDate(tmpDate.getDate() - 1);
        if ((tmpDate.getDay() === 1) && tmpDate.getMonth() !== fromDate.getMonth()) {
          return tmpDate;
        }
      }
      throw new Error('failed to calc viewFrom date');
    }

    function calcViewToDate(fromDate) {
      var i, tmpDate = new Date(fromDate.valueOf());
      for (i = 0; i < 42; i++) {
        tmpDate.setDate(tmpDate.getDate() + 1);
      }
      return tmpDate;
    }
  }

  _onTodayClick(event) {
    this.selectedDate = new Date();
    this._updateModel(true, false);
  }

  _onDisplayModeClick(event) {
    var displayMode = $(event.target).data('mode');
    this.setDisplayMode(displayMode);
  }

  _onYearClick(event) {
    this._showYearPanel = !this._showYearPanel;
    this._updateScreen(true, true);
  }

  _onListClick(event) {
    this._showListPanel = !this._showListPanel;
    this._updateScreen(false, true);
  }

  _onDayMouseDown(withTime, event) {
    var selectedDate = new Date($(event.delegateTarget).data('date'));
    if (withTime && (this._isDay() || this._isWeek() || this._isWorkWeek())) {
      var seconds = Math.floor(event.originalEvent.layerY / this.heightPerDivision) / this.numberOfHourDivisions * 60 * 60;
      if (seconds < 60 * 60 * 24) {
        selectedDate.setSeconds(seconds);
      }
    }
    this._setSelection(selectedDate, null, false);
  }

  /**
   * @param selectedDate
   * @param selectedComponent may be null when a day is selected
   */
  _setSelection(selectedDate, selectedComponent, updateScrollPosition) {
    var changed = false;

    // selected date
    if (dates.compareDays(this.selectedDate, selectedDate) !== 0) {
      changed = true;
      $('.calendar-day', this.$container).each(function(index, element) {
        var $day = $(element),
          date = $day.data('date');
        if (!date || dates.compareDays(date, this.selectedDate) === 0) {
          $day.select(false); // de-select old date
        } else if (dates.compareDays(date, selectedDate) === 0) {
          $day.select(true); // select new date
        }
      }.bind(this));
      this.selectedDate = selectedDate;
    }

    // selected component / part (may be null)
    if (this.selectedComponent !== selectedComponent) {
      changed = true;
      if (this.selectedComponent) {
        this.selectedComponent.setSelected(false);
      }
      if (selectedComponent) {
        selectedComponent.setSelected(true);
      }
      this.selectedComponent = selectedComponent;
    }

    if (changed) {
      this.trigger('selectionChange');
      this._updateListPanel();
      if (updateScrollPosition) {
        this._updateScrollPosition(false, true);
      }
    }

    if (this._showYearPanel) {
      this._yearPanel.selectDate(this.selectedDate);
    }
  }

  /* --  set display mode and range ------------------------------------- */

  _updateScreen(updateTopGrid, animate) {
    $.log.isInfoEnabled() && $.log.info('(Calendar#_updateScreen)');

    // select mode
    $('.calendar-mode', this.$commands).select(false);
    $('[data-mode="' + this.displayMode + '"]', this.$commands).select(true);

    // remove selected day
    $('.selected', this.$grid).select(false);

    // layout grid
    this.layoutLabel();
    this.layoutSize(animate);
    this.layoutAxis();

    if (this._showYearPanel) {
      this._yearPanel.selectDate(this.selectedDate);
    }

    this._updateListPanel();
    this._updateScrollbars(this.$grid, animate);
    if (updateTopGrid && !this._isMonth()) {
      this._updateTopGrid();
    }
  }

  layoutSize(animate) {
    // reset animation sizes
    $('div', this.$container).removeData(['new-width', 'new-height']);

    if (this._isMonth()) {
      this.$topGrid.addClass('calendar-top-grid-short');
      this.$grid.removeClass('calendar-grid-short');
    } else {
      this.$topGrid.removeClass('calendar-top-grid-short');
      this.$grid.addClass('calendar-grid-short');
    }

    // init vars (Selected: Day)
    var $selected = $('.selected', this.$grid),
      $topSelected = $('.selected', this.$topGrid),
      containerW = this.$container.width(),
      gridH = this.$grid.height(),
      gridW = containerW - 20; // containerW - @root-group-box-padding-right

    // show or hide year
    $('.calendar-toggle-year', this.$commands).select(this._showYearPanel);
    if (this._showYearPanel) {
      this._yearPanel.$container.data('new-width', this.calendarToggleYearWidth);
      gridW -= this.calendarToggleYearWidth;
      containerW -= this.calendarToggleYearWidth;
    } else {
      this._yearPanel.$container.data('new-width', 0);
    }

    // show or hide work list
    $('.calendar-toggle-list', this.$commands).select(this._showListPanel);
    if (this._showListPanel) {
      this.$list.parent().data('new-width', this.calendarToggleListWidth);
      gridW -= this.calendarToggleListWidth;
      containerW -= this.calendarToggleListWidth;
    } else {
      this.$list.parent().data('new-width', 0);
    }

    // basic grid width
    this.$grids.data('new-width', containerW);

    var $weeksToHide = $(); // Empty
    var $allWeeks = $('.calendar-week', this.$grid);
    // layout week

    if (this._isDay() || this._isWeek() || this._isWorkWeek()) {
      $allWeeks.removeClass('calendar-week-noborder');
      // Parent of selected (Day) is a week
      var selectedWeek = $selected.parent();
      $weeksToHide = $allWeeks.not(selectedWeek); // Hide all (other) weeks delayed, height will animate to zero
      $weeksToHide.data('new-height', 0);
      $weeksToHide.removeClass('invisible');
      selectedWeek.data('new-height', this.heightPerDay);
      selectedWeek.addClass('calendar-week-noborder');
      selectedWeek.removeClass('hidden invisible'); // Current week must be shown
      $('.calendar-day', selectedWeek).data('new-height', this.heightPerDay);
      // Hide the week-number in the lower grid
      $('.calendar-week-name', this.$grid).addClass('invisible'); // Keep the reserved space
      $('.calendar-week-allday-container', this.$topGrid).removeClass('hidden');
      $('.calendar-week-task', this.$topGrid).removeClass('hidden');
    } else {
      // Month
      var newHeightMonth = gridH / this.monthViewNumberOfWeeks;
      $allWeeks.removeClass('calendar-week-noborder invisible hidden');
      $allWeeks.eq(0).addClass('calendar-week-noborder');
      $allWeeks.data('new-height', newHeightMonth);
      $('.calendar-day', this.$grid).data('new-height', newHeightMonth);
      var $allDays = $('.calendar-week-name', this.$grid);
      $allDays.removeClass('hidden invisible');
      $allDays.data('new-height', newHeightMonth);
      $('.calendar-week-allday-container', this.$topGrid).addClass('hidden');
      $('.calendar-week-task', this.$topGrid).addClass('hidden');
    }

    // layout days
    var contentW = gridW - 45; // gridW - @calendar-week-name-width
    if (this._isDay()) {
      $('.calendar-day-name, .calendar-day', this.$topGrid).data('new-width', 0);
      $('.calendar-day', this.$grid).data('new-width', 0);
      $('.calendar-day-name:nth-child(' + ($topSelected.index() + 1) + ')', this.$topGrid)
        .data('new-width', contentW);
      $('.calendar-day:nth-child(' + ($topSelected.index() + 1) + ')', this.$topGrid).data('new-width', contentW);
      $('.calendar-day:nth-child(' + ($selected.index() + 1) + ')', this.$grid).data('new-width', contentW);
    } else if (this._isWorkWeek()) {
      this.$topGrid.find('.calendar-day-name').data('new-width', 0);
      this.$grids.find('.calendar-day').data('new-width', 0);
      var newWidthWorkWeek = Math.round(contentW / this.workDayIndices.length);
      $('.calendar-day-name:nth-child(-n+6), ' +
        '.calendar-day:nth-child(-n+6)', this.$topGrid)
        .data('new-width', newWidthWorkWeek);
      $('.calendar-day:nth-child(-n+6)', this.$grid)
        .data('new-width', newWidthWorkWeek);
    } else if (this._isMonth() || this._isWeek()) {
      var newWidthMonthOrWeek = Math.round(contentW / 7);
      this.$grids.find('.calendar-day').data('new-width', newWidthMonthOrWeek);
      this.$topGrid.find('.calendar-day-name').data('new-width', newWidthMonthOrWeek);
    }

    // layout components
    if (this._isMonth()) {
      $('.component-month', this.$grid).each(function() {
        var $comp = $(this),
          $day = $comp.closest('.calendar-day');
        $comp.toggleClass('compact', $day.data('new-width') < CalendarComponent.MONTH_COMPACT_THRESHOLD);
      });
    }

    var afterLayoutCallback = this._afterLayout.bind(this);

    // animate old to new sizes
    $('div', this.$container).each(function() {
      var $e = $(this),
        w = $e.data('new-width'),
        h = $e.data('new-height');
      $e.stop(false, true);

      if (w !== undefined && w !== $e.outerWidth()) {
        if (animate) {
          $e.animateAVCSD('width', w, afterLayoutCallback.bind(this, $e, animate));
        } else {
          $e.css('width', w);
          afterLayoutCallback($e, animate);
        }
      }
      if (h !== undefined && h !== $e.outerHeight()) {
        if (h > 0) {
          $e.removeClass('hidden');
        }
        if (animate) {
          $e.animateAVCSD('height', h, function() {
            if (h === 0) {
              $e.addClass('hidden');
            }
            afterLayoutCallback($e, animate);
          });
        } else {
          $e.css('height', h);
          if (h === 0) {
            $e.addClass('hidden');
          }
          afterLayoutCallback($e, animate);
        }
      }
    });
  }

  _afterLayout($parent, animate) {
    this._updateScrollbars($parent, animate);
    this._updateWeekdayNames();
  }

  _updateWeekdayNames() {
    // set day-name (based on width of shown column)
    var weekdayWidth = this.$topGrid.width(),
      weekdays;

    if (this._isDay()) {
      weekdayWidth /= 1;
    } else if (this._isWorkWeek()) {
      weekdayWidth /= this.workDayIndices.length;
    } else if (this._isWeek()) {
      weekdayWidth /= 7;
    } else if (this._isMonth()) {
      weekdayWidth /= 7;
    }

    if (weekdayWidth > 90) {
      weekdays = this.session.locale.dateFormat.symbols.weekdaysOrdered;
    } else {
      weekdays = this.session.locale.dateFormat.symbols.weekdaysShortOrdered;
    }

    $('.calendar-day-name', this.$topGrid).each(function(index) {
      $(this).attr('data-day-name', weekdays[index]);
    });
  }

  _updateScrollbars($parent, animate) {
    var $scrollables = $('.calendar-scrollable-components', $parent);
    $scrollables.each(function() {
      var $scrollable = $(this);
      scrollbars.update($scrollable, true);
    });
    this.updateScrollPosition(animate);
  }

  _updateTopGrid() {
    $('.calendar-component', this.$topGrid).each((index, part) => {
      let component = $(part).data('component');
      if (component) {
        component.remove();
      }
    });
    var allDayComponents = this.components.filter(component => component.fullDay);
    // first remove all components and add them from scratch
    allDayComponents.forEach(component => component.remove());
    allDayComponents.forEach(component => component.render());
    this._updateScrollbars(this.$topGrid, false);
  }

  layoutYearPanel() {
    if (this._showYearPanel) {
      scrollbars.update(this._yearPanel.$yearList);
      this._yearPanel._scrollYear();
    }
  }

  layoutLabel() {
    var text, $dates, $topGridDates,
      exFrom = this._exactRange.from,
      exTo = this._exactRange.to;

    // set range text
    if (this._isDay()) {
      text = this._format(exFrom, 'd. MMMM yyyy');
    } else if (this._isWorkWeek() || this._isWeek()) {
      var toText = this.session.text('ui.to');
      if (exFrom.getMonth() === exTo.getMonth()) {
        text = strings.join(' ', this._format(exFrom, 'd.'), toText, this._format(exTo, 'd. MMMM yyyy'));
      } else if (exFrom.getFullYear() === exTo.getFullYear()) {
        text = strings.join(' ', this._format(exFrom, 'd. MMMM'), toText, this._format(exTo, 'd. MMMM yyyy'));
      } else {
        text = strings.join(' ', this._format(exFrom, 'd. MMMM yyyy'), toText, this._format(exTo, 'd. MMMM yyyy'));
      }

    } else if (this._isMonth()) {
      text = this._format(exFrom, 'MMMM yyyy');
    }
    this.$select.text(text);

    // prepare to set all day date and mark selected one
    $dates = $('.calendar-day', this.$grid);

    var w, d, cssClass,
      currentMonth = this._exactRange.from.getMonth(),
      date = new Date(this.viewRange.from.valueOf());

    // Main grid: loop all days and set value and class
    for (w = 0; w < this.monthViewNumberOfWeeks; w++) {
      for (d = 0; d < 7; d++) {
        cssClass = '';
        if (this.workDayIndices.indexOf(date.getDay()) === -1) {
          cssClass = date.getMonth() !== currentMonth ? ' weekend-out' : ' weekend';
        } else {
          cssClass = date.getMonth() !== currentMonth ? ' out' : '';
        }
        if (dates.isSameDay(date, new Date())) {
          cssClass += ' now';
        }
        if (dates.isSameDay(date, this.selectedDate)) {
          cssClass += ' selected';
        }
        if (!this._isMonth()) {
          cssClass += ' calendar-no-label'; // If we're not in the month view, number is shown on top
        }

        // adjust position for days between 10 and 19 (because "1" is narrower than "0" or "2")
        if (date.getDate() > 9 && date.getDate() < 20) {
          cssClass += ' center-nice';
        }

        text = this._format(date, 'dd');
        $dates.eq(w * 7 + d)
          .removeClass('weekend-out weekend out selected now calendar-no-label')
          .addClass(cssClass)
          .attr('data-day-name', text)
          .data('date', new Date(date.valueOf()));
        date.setDate(date.getDate() + 1);
      }
    }

    // Top grid: loop days of one calendar week and set value and class
    if (!this._isMonth()) {
      $topGridDates = $('.calendar-day', this.$topGrid);
      // From the view range, find the week we are in
      var exactDate = new Date(this._exactRange.from.valueOf());

      // Find first day of week.
      date = dates.firstDayOfWeek(exactDate, 1);

      for (d = 0; d < 7; d++) {
        cssClass = '';
        if (this.workDayIndices.indexOf(date.getDay()) === -1) {
          cssClass = date.getMonth() !== currentMonth ? ' weekend-out' : ' weekend';
        } else {
          cssClass = date.getMonth() !== currentMonth ? ' out' : '';
        }
        if (dates.isSameDay(date, new Date())) {
          cssClass += ' now';
        }
        if (dates.isSameDay(date, this.selectedDate)) {
          cssClass += ' selected';
        }

        text = this._format(date, 'dd');
        $topGridDates.eq(d)
          .removeClass('weekend-out weekend out selected now')
          .addClass(cssClass)
          .attr('data-day-name', text)
          .data('date', new Date(date.valueOf()));

        date.setDate(date.getDate() + 1);
      }
    }

  }

  layoutAxis() {
    var $e;

    // remove old axis
    $('.calendar-week-axis, .calendar-week-task', this.$grid).remove();

    // set weekname
    var session = this.session;

    $('.calendar-week-name', this.$container).each(function(index) {
      if (index > 0) {
        $e = $(this);
        $e.text(session.text('ui.CW', dates.weekInYear($e.next().data('date'))));
      }
    });

    // day schedule
    if (!this._isMonth()) {
      // Parent of selected day: Week
      //    var $parent = $selected.parent();
      var $parent = $('.calendar-week', this.$grid);

      for (var h = 0; h < 24; h++) { // Render lines for each hour
        var paddedHour = ('00' + h).slice(-2);
        var topPos = h * this.heightPerHour;
        $parent.appendDiv('calendar-week-axis hour' + (h === 0 ? ' first' : '')).attr('data-axis-name', paddedHour + ':00').css('top', topPos + 'px');

        for (var m = 1; m < this.numberOfHourDivisions; m++) { // First one rendered above. Start at the next
          topPos += this.heightPerDivision;
          $parent.appendDiv('calendar-week-axis').attr('data-axis-name', '').css('top', topPos + 'px');
        }
      }
    }
  }

  /* -- year events ---------------------------------------- */

  _onYearPanelDateSelect(event) {
    this.selectedDate = event.date;
    this._updateModel(true, false);
  }

  _updateListPanel() {
    if (this._showListPanel) {

      // remove old list-components
      this._listComponents.forEach(function(listComponent) {
        listComponent.remove();
      });

      this._listComponents = [];
      this._renderListPanel();
    }
  }

  _remove() {
    var $days = $('.calendar-day', this.$grid);

    // Ensure that scrollbars are unregistered
    for (var k = 0; k < $days.length; k++) {
      var $day = $days.eq(k);
      var $scrollableContainer = $day.children('.calendar-scrollable-components');

      if ($scrollableContainer.length > 0) {
        scrollbars.uninstall($scrollableContainer, this.session);
        $scrollableContainer.remove();
      }
    }

    super._remove();
  }

  /**
   * Renders the panel on the left, showing all components of the selected date.
   */
  _renderListPanel() {
    var listComponent, components = [];

    // set title
    this.$listTitle.text(this._format(this.selectedDate, 'd. MMMM yyyy'));

    // find components to display on the list panel
    this.components.forEach(function(component) {
      if (belongsToSelectedDate.call(this, component)) {
        components.push(component);
      }
    }.bind(this));

    function belongsToSelectedDate(component) {
      var selectedDate = dates.trunc(this.selectedDate);
      return dates.compare(selectedDate, component.coveredDaysRange.from) >= 0 &&
        dates.compare(selectedDate, component.coveredDaysRange.to) <= 0;
    }

    components.forEach(function(component) {
      listComponent = new CalendarListComponent(this.selectedDate, component);
      listComponent.render(this.$list);
      this._listComponents.push(listComponent);
    }.bind(this));
  }

  /* -- components, events-------------------------------------------- */

  _selectedComponentChanged(component, partDay, updateScrollPosition) {
    this._setSelection(partDay, component, updateScrollPosition);
  }

  _onDayContextMenu(event) {
    this._showContextMenu(event, 'Calendar.EmptySpace');
  }

  _showContextMenu(event, allowedType) {
    event.preventDefault();
    event.stopPropagation();

    var func = function func(event, allowedType) {
      if (!this.rendered || !this.attached) { // check needed because function is called asynchronously
        return;
      }
      var filteredMenus = menus.filter(this.menus, [allowedType], true),
        $part = $(event.currentTarget);
      if (filteredMenus.length === 0) {
        return;
      }
      var popup = scout.create('ContextMenuPopup', {
        parent: this,
        menuItems: filteredMenus,
        location: {
          x: event.pageX,
          y: event.pageY
        },
        $anchor: $part
      });
      popup.open();
    }.bind(this);

    this.session.onRequestsDone(func, event, allowedType);
  }

  /* -- components, arrangement------------------------------------ */

  _arrangeComponents() {
    var k, j, $day, $allChildren, $children, $scrollableContainer, dayComponents, day;

    var $days = $('.calendar-day', this.$grid);
    // Main (Bottom) grid: Iterate over days
    for (k = 0; k < $days.length; k++) {
      $day = $days.eq(k);
      $children = $day.children('.calendar-component:not(.component-task)');
      $allChildren = $day.children('.calendar-component');
      day = $day.data('date');

      // Remove old element containers
      $scrollableContainer = $day.children('.calendar-scrollable-components');
      if ($scrollableContainer.length > 0) {
        scrollbars.uninstall($scrollableContainer, this.session);
        $scrollableContainer.remove();
      }

      if (this._isMonth() && $allChildren.length > 0) {
        $scrollableContainer = $day.appendDiv('calendar-scrollable-components');

        for (j = 0; j < $allChildren.length; j++) {
          var $child = $allChildren.eq(j);
          // non-tasks (communications) are distributed manually
          // within the parent container in all views except the monthly view.
          if (!this._isMonth() && !$child.hasClass('component-task')) {
            continue;
          }
          $scrollableContainer.append($child);
        }

        scrollbars.install($scrollableContainer, {
          parent: this,
          session: this.session,
          axis: 'y'
        });
      }

      if (this._isMonth() && $children.length > 2) {
        $day.addClass('many-items');
      } else if (!this._isMonth() && $children.length > 1) {
        // logical placement
        dayComponents = this._getComponents($children);
        this._arrange(dayComponents, day);

        // screen placement
        this._arrangeComponentSetPlacement($children, day);
      }
    }

    if (this._isMonth()) {
      this._uninstallScrollbars();
      this.$grid.removeClass('calendar-scrollable-components');
    } else {
      this.$grid.addClass('calendar-scrollable-components');
      // If we're in the non-month views, the time can scroll. Add scrollbars
      this._installScrollbars({
        parent: this,
        session: this.session,
        axis: 'y'
      });

      var $topDays = $('.calendar-scrollable-components', this.$topGrid);
      for (k = 0; k < $topDays.length; k++) {
        var $topDay = $topDays.eq(k);
        scrollbars.install($topDay, {
          parent: this,
          session: this.session,
          axis: 'y'
        });
      }
    }
  }

  _getComponents($children) {
    var i, $child;
    var components = [];
    for (i = 0; i < $children.length; i++) {
      $child = $children.eq(i);
      components.push($child.data('component'));
    }
    return components;
  }

  _sort(components) {
    components.sort(this._sortFromTo);
  }

  /**
   * Arrange components (stack width, stack index) per day
   * */
  _arrange(components, day) {
    var i, j, c, r, k,
      columns = [];

    // ordered by from, to
    this._sort(components);

    // clear existing placement
    for (i = 0; i < components.length; i++) {
      c = components[i];
      if (!c.stack) {
        c.stack = {};
      }
      c.stack[day] = {};
    }

    for (i = 0; i < components.length; i++) {
      c = components[i];
      r = c.getPartDayPosition(day); // Range [from,to]

      // reduce number of columns, if all components end before this one
      if (columns.length > 0 && this._allEndBefore(columns, r.from, day)) {
        columns = [];
      }

      // replace an component that ends before and can be replaced
      k = this._findReplacableColumn(columns, r.from, day);

      // insert
      if (k >= 0) {
        columns[k] = c;
        c.stack[day].x = k;
      } else {
        columns.push(c);
        c.stack[day].x = columns.length - 1;
      }

      // update stackW
      for (j = 0; j < columns.length; j++) {
        columns[j].stack[day].w = columns.length;
      }
    }
  }

  _allEndBefore(columns, pos, day) {
    var i;
    for (i = 0; i < columns.length; i++) {
      if (!this._endsBefore(columns[i], pos, day)) {
        return false;
      }
    }
    return true;
  }

  _findReplacableColumn(columns, pos, day) {
    var j;
    for (j = 0; j < columns.length; j++) {
      if (this._endsBefore(columns[j], pos, day)) {
        return j;
      }
    }
    return -1;
  }

  _endsBefore(component, pos, day) {
    return component.getPartDayPosition(day).to <= pos;
  }

  _arrangeComponentSetPlacement($children, day) {
    var i, $child, stack;

    // loop and place based on data
    for (i = 0; i < $children.length; i++) {
      $child = $children.eq(i);
      stack = $child.data('component').stack[day];

      // make last element smaller
      $child
        .css('width', 100 / stack.w + '%')
        .css('left', stack.x * 100 / stack.w + '%');
    }
  }

  get$Scrollable() {
    return this.$grid;
  }

  /* -- helper ---------------------------------------------------- */

  _dayPosition(hour, minutes) {
    // Height position in percent of total calendar

    var pos;
    if (hour < 0) {
      pos = 0; // All day event
    } else {
      pos = 100 / (24 * 60) * (hour * 60 + minutes);
    }
    return Math.round(pos * 100) / 100;
  }

  _hourToNumber(hour) {
    var splits = hour.split(':');
    return parseFloat(splits[0]) + parseFloat(splits[1]) / 60;
  }

  _format(date, pattern) {
    return dates.format(date, this.session.locale, pattern);
  }

  _sortFromTo(c1, c2) {
    var from1 = dates.parseJsonDate(c1.fromDate);
    var from2 = dates.parseJsonDate(c2.fromDate);
    var diffFrom = dates.compare(from1, from2);
    if (diffFrom !== 0) {
      return diffFrom;
    }
    var to1 = dates.parseJsonDate(c1.toDate);
    var to2 = dates.parseJsonDate(c2.toDate);
    var diffTo = dates.compare(to1, to2);
    if (diffTo !== 0) {
      return diffTo;
    }
    var s1 = c1.item && c1.item.subject ? c1.item.subject : '';
    var s2 = c2.item && c2.item.subject ? c2.item.subject : '';
    return s1.localeCompare(s2);
  }
}
