import React, { useCallback, useMemo, useState, useEffect } from "react";
import classNames from "classnames";
import moment from "moment";
import { StyledButton, StyledButtonGroup, StyledDiv, StyledMenu, StyledSpan, StyledControl } from "./Styles";
import { DatePicker } from "../../DatePicker";
import { ArrowRightIcon } from "../../Icons";
import ArrowLeftIcon from "../../Icons/collection/ArrowLeft";
/**
 * This component allow you to select date range. It accepts two parameters "from" and "to" as valid format
 * onChange and onBack and onForward it will return "from: Date" and "to: Date" as function arguments
 */

export const DateStepper = _ref => {
  let {
    step,
    formatCallback,
    onChange,
    from,
    to,
    onBack,
    onForward,
    minValue,
    maxValue,
    className,
    period = "week",
    datePickerClass,
    withDatePicker = true,
    defaultMonth = new Date(),
    popperClassName,
    position = "bottom"
  } = _ref;
  const [fromDate, setFromDate] = useState(moment(from));
  const [toDate, setToDate] = useState(moment(to));
  const [showDatePicker, setShowDatePicker] = useState(false);
  const [month, setMonth] = useState(defaultMonth);
  const getDatesByPeriod = useCallback(interval => {
    const date = fromDate ? fromDate : moment();
    if (step === "daily") {
      date.add(interval, "days");
      return [date, date.clone()];
    } else if (step === "weekly") {
      date.add(interval, "weeks");
      return [date.clone().startOf(period), date.clone().endOf(period)];
    } else if (step === "monthly") {
      date.add(interval, "months");
      return [date.clone().startOf("month"), date.clone().endOf("month")];
    } else if (step === "quarterly") {
      date.add(interval, "quarters");
      return [date.clone().startOf("quarter"), date.clone().endOf("quarter")];
    } else if (step === "yearly") {
      date.add(interval, "years");
      return [date.clone().startOf("year"), date.clone().endOf("year")];
    }
    return [date, date];
  }, [fromDate, period, step]);
  const getDateFormatted = useMemo(() => {
    if (formatCallback) {
      return formatCallback(fromDate.toDate(), toDate.toDate());
    }
    const actualYear = moment().year();
    const showWeekOrCustomDateFormat = (start, end) => {
      if (start.year() === actualYear && end.year() === actualYear) {
        return start.format("MMM DD") + " - " + end.format("MMM DD");
      } else {
        return start.format("MMM DD YYYY") + " - " + end.format("MMM DD YYYY");
      }
    };
    if (step === "daily") {
      if (fromDate.year() === actualYear) {
        return fromDate.format("MMM DD");
      }
      return fromDate.format("MMM DD YYYY");
    } else if (step === "weekly") {
      const startDate = fromDate.clone().startOf(period);
      const endDate = startDate.clone().endOf(period);
      return showWeekOrCustomDateFormat(startDate, endDate);
    } else if (step === "monthly") {
      return fromDate.format("MMM YYYY");
    } else if (step === "quarterly") {
      return "Q" + fromDate.quarter() + "/" + fromDate.format("YYYY");
    } else if (step === "yearly") {
      return fromDate.format("YYYY");
    } else if (step === "custom") {
      return showWeekOrCustomDateFormat(fromDate, toDate);
    }
    return "";
  }, [fromDate, step, toDate, formatCallback, period]);
  const onChangeCallback = useCallback(amount => {
    const [newFrom, newTo] = getDatesByPeriod(amount);
    setFromDate(moment(newFrom));
    setToDate(moment(newTo));
    if (onChange) {
      onChange(newFrom.toDate(), newTo.toDate());
    }
  }, [onChange, getDatesByPeriod]);
  const onDatePickerChange = useCallback(dates => {
    const fromDateTemp = dates == null ? void 0 : dates.from;
    const toDateTemp = dates == null ? void 0 : dates.to;
    setFromDate(moment(fromDateTemp));
    setToDate(moment(toDateTemp));
    if (onChange && fromDateTemp instanceof Date && toDateTemp instanceof Date) {
      onChange(fromDateTemp, toDateTemp);
    }
  }, [onChange, setFromDate, setToDate]);
  const isAfterMaxDate = useMemo(() => {
    return maxValue instanceof Date && moment(moment(maxValue).format("YYYY-MM-DD")).isSameOrBefore(toDate.format("YYYY-MM-DD"));
  }, [maxValue, toDate]);
  const isBeforeMinDate = useMemo(() => {
    return minValue instanceof Date && moment(moment(minValue).format("YYYY-MM-DD")).isSameOrAfter(toDate.format("YYYY-MM-DD"));
  }, [minValue, toDate]);
  useEffect(() => {
    if (isBeforeMinDate) {
      if (step === "daily") {
        setFromDate(moment(minValue));
        setToDate(moment(minValue));
      }
    }
    if (isAfterMaxDate) {
      if (step === "daily") {
        setFromDate(moment(maxValue));
        setToDate(moment(maxValue));
      }
    }
  }, [step, minValue, maxValue, isBeforeMinDate, isAfterMaxDate]);
  const onRightClickHandler = useCallback(() => {
    if (isAfterMaxDate) {
      return;
    }
    onChangeCallback(1);
    if (onForward) {
      onForward(fromDate.toDate(), toDate.toDate());
    }
  }, [isAfterMaxDate, onChangeCallback, onForward, fromDate, toDate]);
  const onLeftClickHandler = useCallback(() => {
    if (isBeforeMinDate) {
      return;
    }
    onChangeCallback(-1);
    if (onBack) {
      onBack(fromDate.toDate(), toDate.toDate());
    }
  }, [isBeforeMinDate, onChangeCallback, onBack, fromDate, toDate]);
  const renderLeftRightButtons = useMemo(() => {
    return step !== "custom";
  }, [step]);
  const handleShow = useCallback(() => {
    setShowDatePicker(!showDatePicker);
    if (fromDate) {
      setMonth(fromDate.toDate());
    }
  }, [setShowDatePicker, showDatePicker, fromDate]);
  const closeMenu = useCallback(() => {
    setShowDatePicker(false);
  }, []);
  const onMonthChange = useCallback(m => {
    setMonth(m);
  }, [setMonth]);
  useEffect(() => {
    setFromDate(moment(from));
    setToDate(moment(to));
  }, [from, to]);
  const dateStepperWidth = (fromDay, toDay, range) => {
    if (fromDay.year() !== moment().year() || toDay.year() !== moment().year()) {
      switch (range) {
        case "daily":
        case "monthly":
          return {
            minWidth: "122px"
          };
        case "weekly":
        case "custom":
          return {
            minWidth: "232px"
          };
      }
    }
    switch (range) {
      case "monthly":
        return {
          minWidth: "122px"
        };
      case "weekly":
      case "custom":
        return {
          minWidth: "182px"
        };
    }
    return {
      minWidth: "102px"
    };
  };
  const isDisabled = useCallback(day => {
    const dayFormat = moment(day).format("YYYY-MM-DD");
    const isBefore = maxValue instanceof Date && moment(moment(maxValue).format("YYYY-MM-DD")).isBefore(dayFormat);
    const isAfter = minValue instanceof Date && moment(moment(minValue).format("YYYY-MM-DD")).isAfter(dayFormat);
    return isBefore || isAfter;
  }, [maxValue, minValue]);
  const modifiers = useMemo(() => {
    return {
      day_disabled: day => {
        return isDisabled(day);
      },
      nonWorkingDay: day => {
        return isDisabled(day);
      }
    };
  }, [isDisabled]);
  return /*#__PURE__*/React.createElement(StyledButtonGroup, {
    className: classNames("c-date-stepper", className)
  }, renderLeftRightButtons ? /*#__PURE__*/React.createElement(StyledControl, {
    type: "button",
    variant: "secondary",
    onClick: onLeftClickHandler,
    disabled: isBeforeMinDate
  }, /*#__PURE__*/React.createElement(ArrowLeftIcon, null)) : null, /*#__PURE__*/React.createElement(StyledDiv, {
    $isTargetable: step === "yearly" || !withDatePicker,
    $isRounded: step === "custom",
    style: dateStepperWidth(fromDate, toDate, step)
  }, withDatePicker ? /*#__PURE__*/React.createElement(StyledMenu, {
    target: /*#__PURE__*/React.createElement(StyledButton, {
      type: "button"
    }, /*#__PURE__*/React.createElement("span", null, getDateFormatted)),
    open: showDatePicker,
    onOpen: handleShow,
    onClose: closeMenu,
    popperClassName: popperClassName,
    position: position
  }, /*#__PURE__*/React.createElement(DatePicker, {
    month: month,
    selectionMode: step,
    className: datePickerClass,
    selectedDays: {
      from: fromDate.toDate(),
      to: toDate.toDate()
    },
    onChange: onDatePickerChange,
    onMonthChange: onMonthChange,
    firstDayOfWeek: period === "week" ? 0 : 1,
    modifiers: modifiers,
    dateRequired: true,
    fixedWeeks: true
  })) : /*#__PURE__*/React.createElement(StyledSpan, null, getDateFormatted)), renderLeftRightButtons ? /*#__PURE__*/React.createElement(StyledControl, {
    type: "button",
    variant: "secondary",
    onClick: onRightClickHandler,
    disabled: isAfterMaxDate
  }, /*#__PURE__*/React.createElement(ArrowRightIcon, null)) : null);
};
DateStepper.displayName = "DateStepper";
//# sourceMappingURL=DateStepper.js.map