"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Calendar = void 0;

var _preact = require("preact");

var _classnames = _interopRequireDefault(require("classnames"));

var _button = require("./button");

var _icon = require("./icon");

var _date = require("./utils/date");

var _eachWeekOfInterval = _interopRequireDefault(require("date-fns/eachWeekOfInterval"));

var _startOfMonth = _interopRequireDefault(require("date-fns/startOfMonth"));

var _endOfDay = _interopRequireDefault(require("date-fns/endOfDay"));

var _addMonths = _interopRequireDefault(require("date-fns/addMonths"));

var _endOfMonth = _interopRequireDefault(require("date-fns/endOfMonth"));

var _endOfWeek = _interopRequireDefault(require("date-fns/endOfWeek"));

var _eachDayOfInterval = _interopRequireDefault(require("date-fns/eachDayOfInterval"));

var _addWeeks = _interopRequireDefault(require("date-fns/addWeeks"));

var _startOfWeek = _interopRequireDefault(require("date-fns/startOfWeek"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

const Day = ({
  start,
  end,
  events,
  isToday,
  isFuture,
  isPast,
  isCurrentMonth,
  isBottomRow,
  isTopRow,
  isFirstColumn,
  isLastColumn,
  onDayClick,
  dateNumber,
  dayContentComponent: DayContentComponent
}) => {
  const monthName = dateNumber === 1 ? start.toLocaleDateString(undefined, {
    month: 'short'
  }) : null;
  return (0, _preact.h)("div", {
    "data-e2e": "day",
    "data-state": (0, _date.toSimpleISODateString)(start),
    "data-current-month": isCurrentMonth ? 'current' : null,
    className: (0, _classnames.default)('db shadow-1 br2 ba b--light-gray', !isCurrentMonth && 'bg-near-white'),
    style: {
      minHeight: '64px'
    },
    onClick: () => {
      if (onDayClick) {
        onDayClick(start);
      }
    }
  }, (0, _preact.h)("div", {
    className: "relative fw2 f5 tc"
  }, isToday && (0, _preact.h)("div", {
    style: {
      top: '1px',
      left: '50%',
      marginLeft: '-12px',
      width: '24px',
      height: '24px'
    },
    className: "bg-light-blue br-100 dib dark-blue absolute"
  }), (0, _preact.h)("div", {
    className: (0, _classnames.default)('pa1 mv1 relative', !isToday && !isCurrentMonth && 'mid-gray', !isToday && isCurrentMonth && 'dark-blue')
  }, monthName && (0, _preact.h)("div", {
    className: "absolute top-0 left-0 ml2 mt1 fw2 dn db-l"
  }, monthName), dateNumber)), (0, _preact.h)(DayContentComponent, {
    start,
    end,
    events,
    isToday,
    isFuture,
    isPast,
    isCurrentMonth,
    isBottomRow,
    isTopRow,
    isFirstColumn,
    isLastColumn,
    onDayClick,
    dateNumber
  }));
};

class Calendar extends _preact.Component {
  constructor(props) {
    super(props);
    const currentDayDate = props.currentDayDate;
    this.setDate = this.setDate.bind(this);
    this.nextMonth = this.nextMonth.bind(this);
    this.prevMonth = this.prevMonth.bind(this);
    this.thisMonth = this.thisMonth.bind(this);
    this.setDate(props.dateInMonth || currentDayDate);
  }

  getStartAndEnd(date) {
    const currentMonthStart = (0, _startOfMonth.default)(date);
    const currentMonthEnd = (0, _endOfMonth.default)(date);
    return {
      currentMonthStart,
      currentMonthEnd,
      start: (0, _startOfWeek.default)((0, _addWeeks.default)(currentMonthStart, -1)),
      end: (0, _endOfWeek.default)((0, _addWeeks.default)(currentMonthEnd, 2))
    };
  }

  setDate(date) {
    this.setState({
      selectedDate: date
    });

    if (this.props.onMonthChange) {
      this.props.onMonthChange(this.getStartAndEnd(date));
    }
  }

  nextMonth() {
    this.setDate((0, _addMonths.default)(this.state.selectedDate, 1));
  }

  prevMonth() {
    this.setDate((0, _addMonths.default)(this.state.selectedDate, -1));
  }

  thisMonth() {
    this.setDate(this.props.currentDayDate);
  }

  render() {
    const _this$props = this.props,
          {
      currentDayDate,
      entries,
      dayContentComponent,
      dayComponent,
      onDayClick,
      dateInMonth,
      isLoading
    } = _this$props,
          rest = _objectWithoutProperties(_this$props, ["currentDayDate", "entries", "dayContentComponent", "dayComponent", "onDayClick", "dateInMonth", "isLoading"]);

    const endOfToday = (0, _endOfDay.default)(currentDayDate);
    const date = dateInMonth || this.state.selectedDate;
    const {
      currentMonthStart,
      currentMonthEnd,
      start,
      end
    } = this.getStartAndEnd(date);
    const dayNames = [];
    const weeks = (0, _eachWeekOfInterval.default)({
      start,
      end
    });
    const weeksOfDays = weeks.map((startOfWeek, weekIndex) => {
      const intervals = (0, _eachDayOfInterval.default)({
        start: startOfWeek,
        end: (0, _endOfWeek.default)(startOfWeek)
      });
      const isBottomRow = weekIndex === weeks.length - 1;
      return intervals.map((start, dayIndex) => {
        const isTopRow = weekIndex === 0;

        if (isTopRow) {
          dayNames.push(start.toLocaleDateString(undefined, {
            weekday: 'short'
          }));
        }

        const end = (0, _endOfDay.default)(start);
        return {
          events: entries.filter(entry => // starts and finishes today
          entry.startAsDate >= start && entry.startAsDate <= end || // started before but ends today
          entry.startAsDate <= start && entry.endAsDate >= start),
          start,
          end,
          dateNumber: start.getDate(),
          isToday: currentDayDate.valueOf() === start.valueOf(),
          isPast: start < currentDayDate,
          isFuture: start > endOfToday,
          isCurrentMonth: start < currentMonthEnd && start >= currentMonthStart,
          isTopRow,
          isBottomRow,
          isFirstColumn: dayIndex === 0,
          isLastColumn: dayIndex === intervals.length - 1,
          onDayClick,
          dayContentComponent
        };
      });
    });
    const DayComponent = dayComponent || Day;
    return (0, _preact.h)("div", rest, (0, _preact.h)("div", {
      className: "flex items-center justify-between mb2"
    }, (0, _preact.h)(_button.Button, {
      "data-e2e": "prevMonthButton",
      onClick: this.prevMonth,
      className: "flex items-center"
    }, (0, _preact.h)(_icon.Icon, {
      size: "18",
      icon: "keyboard_arrow_left"
    }), (0, _preact.h)("span", {
      className: "dn db-ns ml1"
    }, "Previous")), (0, _preact.h)("div", {
      "data-e2e": "monthName",
      className: "f3 f1-ns fw1"
    }, currentMonthStart.toLocaleDateString(undefined, {
      month: 'long',
      year: 'numeric'
    })), (0, _preact.h)(_button.Button, {
      "data-e2e": "nextMonthButton",
      onClick: this.nextMonth,
      className: "flex items-center"
    }, (0, _preact.h)("span", {
      className: "dn db-ns mr1"
    }, "Next"), (0, _preact.h)(_icon.Icon, {
      size: "18",
      icon: "keyboard_arrow_right"
    }))), (0, _preact.h)("div", {
      style: {
        display: 'grid',
        gridTemplateColumns: 'repeat(7, minmax(40px, 1fr))'
      },
      "data-e2e": "calendarDayContainer",
      className: "relative"
    }, dayNames.map(name => (0, _preact.h)("div", {
      key: name,
      className: "tc fw2 ttu"
    }, name)), weeksOfDays.map(days => days.map(day => (0, _preact.h)(DayComponent, _extends({
      key: start.toISOString()
    }, day)))), isLoading && (0, _preact.h)("div", {
      "data-e2e": "calendarDataLoading",
      className: "absolute w-100 h-100 flex items-center justify-center"
    }, (0, _preact.h)("div", {
      className: "pa4 br-pill bg-lightest-blue h2 flex items-center justify-center o-70"
    }, "Loading", (0, _preact.h)(_icon.Icon, {
      icon: "loading_dots",
      size: "70"
    })))));
  }

}

exports.Calendar = Calendar;