import _extends from "@babel/runtime/helpers/esm/extends";
import _taggedTemplateLiteralLoose from "@babel/runtime/helpers/esm/taggedTemplateLiteralLoose";
var _templateObject, _templateObject2;
import React, { useImperativeHandle, useRef, useState, useLayoutEffect } from 'react';
import { MobilePopup } from "../../../internal/MobilePopup";
import { useLocaleForControl } from "../../../lib/locale/useLocaleForControl";
import { css, cx } from "../../../lib/theming/Emotion";
import { ThemeContext } from "../../../lib/theming/ThemeContext";
import { CommonWrapper } from "../../../internal/CommonWrapper";
import { Calendar, CalendarDay } from "../../Calendar";
import { Popup } from "../../../internal/Popup";
import { DateInput } from "../../DateInput";
import { isBetween, isGreater, isGreaterOrEqual, isLess, isLessOrEqual } from "../../../lib/date/comparison";
import { ZIndex } from "../../../internal/ZIndex";
import { getRootNode } from "../../../lib/rootNode";
import { getMenuPositions } from "../../../lib/getMenuPositions";
import { Button } from "../../Button";
import { useResponsiveLayout } from "../../ResponsiveLayout";
import { InternalDate } from "../../../lib/date/InternalDate";
import { InternalDateGetter } from "../../../lib/date/InternalDateGetter";
import { ArrowAUpIcon16Light } from "../../../internal/icons2022/ArrowAUpIcon/ArrowAUp16Light";
import { NativeDateInput } from "../../../internal/NativeDateInput";
import { forwardRefAndName } from "../../../lib/forwardRefAndName";
import { LocaleContext } from "../../../lib/locale";
import { isIOS } from "../../../lib/client";
import { getFontSize, styles } from "../DateRangePicker.styles";
import { DateRangePickerSeparator } from "../DateRangePickerSeparator";
import { DateRangePickerContext } from "../DateRangePickerContext";
import { DateRangePickerEnd, DateRangePickerStart } from "../DateRangePickerInput";
import { getDateRangePickerTheme, getMobileDateRangePickerTheme } from "../DateRangePickerTheme";
import { DateRangePickerLocaleHelper } from "../locale";
import { validateDateRangePicker } from "../helpers/validateDateRangePicker";
import { getStateForValue } from "../helpers/getStateForValue";
export var DateRangePickerDataTids = {
  root: 'DateRangePicker__root',
  start: 'DateRangePicker__start',
  end: 'DateRangePicker__end',
  popup: 'DateRangePicker__popup',
  calendar: 'DateRangePicker__calendar',
  todayButton: 'DateRangePicker__todayButton',
  startOptionalButton: 'DateRangePicker__startOptionalButton',
  endOptionalButton: 'DateRangePicker__endOptionalButton',
  mobileStart: 'DateRangePicker__mobileStart',
  mobileEnd: 'DateRangePicker__mobileEnd',
  rangeStart: 'DateRangePicker__rangeStart',
  rangeEnd: 'DateRangePicker__rangeEnd'
};
var DayDateAttribute = 'data-date-range-picker-day';
export var DateRangePicker = Object.assign({
  Start: DateRangePickerStart,
  End: DateRangePickerEnd,
  Separator: DateRangePickerSeparator,
  validate: validateDateRangePicker
}, forwardRefAndName('DateRangePicker', function (props, ref) {
  var _useResponsiveLayout = useResponsiveLayout(),
    isMobile = _useResponsiveLayout.isMobile;
  var locale = useLocaleForControl('DateRangePicker', DateRangePickerLocaleHelper);
  var _useState = useState(),
    startValue = _useState[0],
    setStartValue = _useState[1];
  var _useState2 = useState(false),
    startOptional = _useState2[0],
    setStartOptional = _useState2[1];
  var _useState3 = useState(false),
    startDisabled = _useState3[0],
    setStartDisabled = _useState3[1];
  var _useState4 = useState(),
    endValue = _useState4[0],
    setEndValue = _useState4[1];
  var _useState5 = useState(false),
    endOptional = _useState5[0],
    setEndOptional = _useState5[1];
  var _useState6 = useState(false),
    endDisabled = _useState6[0],
    setEndDisabled = _useState6[1];
  var _useState7 = useState(''),
    minDate = _useState7[0],
    setMinDate = _useState7[1];
  var _useState8 = useState(''),
    maxDate = _useState8[0],
    setMaxDate = _useState8[1];
  var _useState9 = useState(null),
    hoveredDay = _useState9[0],
    setHoveredDay = _useState9[1];
  var _useState10 = useState(false),
    showCalendar = _useState10[0],
    setShowCalendar = _useState10[1];
  var _useState11 = useState(null),
    focusInput = _useState11[0],
    setFocusInput = _useState11[1];
  var dateRangePickerRef = useRef(null);
  var calendarRef = useRef(null);
  var startRef = useRef(null);
  var endRef = useRef(null);
  var mobileStartRef = useRef(null);
  var mobileEndRef = useRef(null);
  var mobileNativeStartRef = useRef(null);
  var mobileNativeEndRef = useRef(null);
  var isCalendarOpen = !startDisabled && !endDisabled && showCalendar;
  var updateDateRangeValues = function updateDateRangeValues(value) {
    if (value === void 0) {
      value = '';
    }
    var currentValues = {
      currentStart: startValue,
      currentEnd: endValue,
      minDate: minDate,
      maxDate: maxDate
    };
    var updatedState = getStateForValue(focusInput, value, currentValues);
    setStartValue(updatedState.start);
    setEndValue(updatedState.end);
    if (updatedState.isOpen && updatedState.focus) {
      focus(updatedState.focus);
    }
    if (!updatedState.isOpen) {
      close();
    }
  };
  var open = function open(inputType) {
    if (inputType === void 0) {
      inputType = 'start';
    }
    setFocusInput(inputType);
    setShowCalendar(true);
  };
  var close = function close() {
    setShowCalendar(false);
    setHoveredDay(null);
  };
  var focus = function focus(inputType) {
    if (inputType === void 0) {
      inputType = 'start';
    }
    setFocusInput(inputType);
  };
  var setEmpty = function setEmpty(type) {
    switch (type) {
      case 'start':
        setStartValue('');
        focus('end');
        break;
      case 'end':
        setEndValue('');
        close();
        break;
    }
  };
  useImperativeHandle(ref, function () {
    return {
      open: open,
      close: close,
      scrollToMonth: function scrollToMonth(month, year) {
        var _calendarRef$current;
        (_calendarRef$current = calendarRef.current) == null || _calendarRef$current.scrollToMonth == null || _calendarRef$current.scrollToMonth(month, year);
      },
      getRootNode: function getRootNode() {
        return dateRangePickerRef.current;
      }
    };
  }, []);
  useLayoutEffect(function () {
    if (!focusInput) {
      return;
    }

    // fix DateInput flushSync warning in React 18
    setTimeout(function () {
      var _currentFieldRef$curr4;
      var isStart = focusInput === 'start';
      var currentFieldRef;

      // Mobile Native Picker
      if (isMobile && props.useMobileNativeDatePicker) {
        currentFieldRef = isStart ? mobileNativeStartRef : mobileNativeEndRef;
        if (isIOS) {
          var _currentFieldRef$curr;
          (_currentFieldRef$curr = currentFieldRef.current) == null || _currentFieldRef$curr.focus();
        } else {
          var _currentFieldRef$curr2;
          // Android open native datepicker only via click
          (_currentFieldRef$curr2 = currentFieldRef.current) == null || _currentFieldRef$curr2.click();
        }
        return;
      }

      // Mobile
      if (isMobile) {
        var _currentFieldRef$curr3;
        currentFieldRef = isStart ? mobileStartRef : mobileEndRef;
        (_currentFieldRef$curr3 = currentFieldRef.current) == null || _currentFieldRef$curr3.focus();
        return;
      }

      // Desktop
      currentFieldRef = isStart ? startRef : endRef;
      (_currentFieldRef$curr4 = currentFieldRef.current) == null || _currentFieldRef$curr4.focus();
    });
  }, [focusInput]);
  var dateRangePickerContextProps = {
    startValue: startValue,
    startOptional: startOptional,
    startDisabled: startDisabled,
    endValue: endValue,
    endOptional: endOptional,
    endDisabled: endDisabled,
    minDate: minDate,
    maxDate: maxDate,
    size: props.size,
    setStartValue: setStartValue,
    setStartOptional: setStartOptional,
    setStartDisabled: setStartDisabled,
    setEndValue: setEndValue,
    setEndOptional: setEndOptional,
    setEndDisabled: setEndDisabled,
    setMinDate: setMinDate,
    setMaxDate: setMaxDate,
    setFocusInput: setFocusInput,
    open: open,
    close: close,
    dateRangePickerRef: dateRangePickerRef,
    startRef: startRef,
    endRef: endRef
  };
  var renderCalendar = function renderCalendar(theme, widthAuto) {
    var _cx;
    if (widthAuto === void 0) {
      widthAuto = false;
    }
    return /*#__PURE__*/(
      React.createElement(LocaleContext.Provider, {
        value: {
          locale: {
            Calendar: {
              months: locale.months,
              dayCellChooseDateAriaLabel: locale.dayCellChooseDateAriaLabel,
              selectMonthAriaLabel: locale.selectMonthAriaLabel,
              selectYearAriaLabel: locale.selectYearAriaLabel,
              selectChosenAriaLabel: locale.selectChosenAriaLabel
            }
          }
        }
      }, /*#__PURE__*/

      React.createElement(Calendar, {
        value: focusInput === 'start' ? startValue : endValue,
        minDate: minDate,
        maxDate: maxDate,
        renderDay: function renderDay(dayProps) {
          return renderCalendarRange(dayProps, theme, props.renderDay);
        },
        onValueChange: function onValueChange(value) {
          return updateDateRangeValues(value);
        },
        ref: calendarRef,
        onMonthChange: props.onMonthChange,
        className: cx((_cx = {}, _cx[styles.calendarWidthAuto()] = widthAuto, _cx))
      }))
    );
  };
  var renderMobileCalendar = function renderMobileCalendar(theme) {
    var _cx2, _cx3;
    return /*#__PURE__*/(
      React.createElement(MobilePopup, {
        opened: true,
        headerChildComponent: /*#__PURE__*/
        React.createElement("div", {
          className: cx(styles.root(theme), styles.inputWrapperWidthFull())
        }, /*#__PURE__*/
        React.createElement(DateInput, {
          withIcon: true,
          value: startValue,
          width: "auto",
          size: "medium",
          className: cx((_cx2 = {}, _cx2[styles.inputVisuallyFocus(theme)] = focusInput === 'start', _cx2)),
          disabled: startDisabled,
          onValueChange: setStartValue,
          onFocus: function onFocus() {
            return setFocusInput('start');
          },
          ref: mobileStartRef,
          "data-tid": DateRangePickerDataTids.mobileStart
        }), /*#__PURE__*/
        React.createElement(DateRangePicker.Separator, null), /*#__PURE__*/
        React.createElement(DateInput, {
          withIcon: true,
          value: endValue,
          width: "auto",
          size: "medium",
          className: cx((_cx3 = {}, _cx3[styles.inputVisuallyFocus(theme)] = focusInput === 'end', _cx3)),
          disabled: endDisabled,
          onValueChange: setEndValue,
          onFocus: function onFocus() {
            return setFocusInput('end');
          },
          ref: mobileEndRef,
          "data-tid": DateRangePickerDataTids.mobileEnd
        })),
        onCloseRequest: function onCloseRequest() {
          return close();
        },
        footerChildComponent: renderButtons()
      }, /*#__PURE__*/

      React.createElement(ThemeContext.Provider, {
        value: getMobileDateRangePickerTheme(theme)
      }, renderCalendar(theme, true)))
    );
  };
  var getAnchorElement = function getAnchorElement() {
    var menuAnchorElement = props.menuAnchorElement;
    if (menuAnchorElement === 'focused') {
      return getRootNode(focusInput === 'start' ? startRef.current : endRef.current);
    }
    if ( /*#__PURE__*/React.isValidElement(menuAnchorElement)) {
      return menuAnchorElement;
    }
    if (menuAnchorElement && typeof menuAnchorElement === 'object' && 'current' in menuAnchorElement) {
      return getRootNode(menuAnchorElement.current);
    }
    return getRootNode(startRef.current) || getRootNode(endRef.current) || getRootNode(dateRangePickerRef.current);
  };
  var renderDesktopCalendar = function renderDesktopCalendar(theme) {
    return /*#__PURE__*/(
      React.createElement(Popup, {
        opened: true,
        hasShadow: true,
        priority: ZIndex.priorities.PopupMenu,
        positions: getMenuPositions(props.menuPos, props.menuAlign),
        "data-tid": DateRangePickerDataTids.root,
        anchorElement: getAnchorElement(),
        margin: parseInt(theme.datePickerMenuOffsetY)
      }, /*#__PURE__*/

      React.createElement("div", {
        className: styles.calendarWrapper(theme),
        onMouseDown: function onMouseDown(e) {
          return e.preventDefault();
        },
        onMouseMove: handleCalendarRangeMouseMove
      }, renderCalendar(theme), renderButtons()))
    );
  };
  var renderButtons = function renderButtons() {
    var today = new InternalDate(locale).setComponents(InternalDateGetter.getTodayComponents()).toString({
      withPad: true,
      withSeparator: true
    });
    var hasOptionalButtons = startOptional || endOptional;
    return /*#__PURE__*/(
      React.createElement("div", {
        className: cx(styles.buttonWrap())
      }, hasOptionalButtons && /*#__PURE__*/
      React.createElement(React.Fragment, null, focusInput === 'start' && startOptional && /*#__PURE__*/
      React.createElement(Button, {
        width: "100%",
        "data-tid": DateRangePickerDataTids.startOptionalButton,
        onClick: function onClick() {
          return setEmpty('start');
        }
      }, locale.startDateEmpty), focusInput === 'end' && endOptional && /*#__PURE__*/
      React.createElement(Button, {
        width: "100%",
        "data-tid": DateRangePickerDataTids.endOptionalButton,
        onClick: function onClick() {
          return setEmpty('end');
        }
      }, locale.endDateEmpty)), props.enableTodayLink && /*#__PURE__*/
      React.createElement(Button, {
        icon: /*#__PURE__*/React.createElement(ArrowAUpIcon16Light, null),
        "aria-label": locale.todayAriaLabel,
        "data-tid": DateRangePickerDataTids.todayButton,
        onClick: function onClick() {
          return updateDateRangeValues(today);
        }
      }, !hasOptionalButtons && locale.today))
    );
  };
  var renderMobileNativeDateInput = function renderMobileNativeDateInput() {
    return /*#__PURE__*/(
      React.createElement(React.Fragment, null, /*#__PURE__*/
      React.createElement(NativeDateInput, {
        value: startValue,
        minDate: minDate,
        maxDate: maxDate,
        onValueChange: setStartValue,
        disabled: startDisabled,
        ref: mobileNativeStartRef
      }), /*#__PURE__*/
      React.createElement(NativeDateInput, {
        value: endValue,
        minDate: minDate,
        maxDate: maxDate,
        onValueChange: setEndValue,
        disabled: endDisabled,
        ref: mobileNativeEndRef
      }))
    );
  };
  return /*#__PURE__*/(
    React.createElement(ThemeContext.Consumer, null, function (theme) {
      return /*#__PURE__*/(
        React.createElement(ThemeContext.Provider, {
          value: getDateRangePickerTheme(theme)
        }, /*#__PURE__*/
        React.createElement(DateRangePickerContext.Provider, {
          value: dateRangePickerContextProps
        }, /*#__PURE__*/
        React.createElement(CommonWrapper, props, /*#__PURE__*/
        React.createElement("div", {
          className: cx(styles.root(theme), styles.inputWrapperWidth(theme), css(_templateObject || (_templateObject = _taggedTemplateLiteralLoose(["\n                      font-size: ", ";\n                    "])), getFontSize(theme, props.size))),
          role: "group",
          "aria-describedby": props['aria-describedby'],
          "aria-label": props['aria-label'],
          "aria-labelledby": props['aria-labelledby'],
          "data-tid": DateRangePickerDataTids.root,
          ref: dateRangePickerRef,
          style: {
            width: props.width
          }
        }, props.children, props.useMobileNativeDatePicker && isMobile ? renderMobileNativeDateInput() : isCalendarOpen && (isMobile ? renderMobileCalendar(theme) : renderDesktopCalendar(theme))))))
      );
    })
  );

  // Use parent mousemove event instead each CalendarDay's mouseenter / mouseover
  function handleCalendarRangeMouseMove(e) {
    if (!startValue && !endValue) {
      return;
    }
    var hoveredElement = e.target;
    if (!hoveredElement.hasAttribute(DayDateAttribute) && hoveredDay === null) {
      return;
    }
    var date = String(hoveredElement == null ? void 0 : hoveredElement.getAttribute(DayDateAttribute)) || null;
    setHoveredDay(date);
  }
  function renderCalendarRange(props, t, renderDayFn) {
    var _extends2, _cx4;
    var day = props.date;
    var isDayFirst = startValue === day;
    var isDayLast = endValue === day;
    var isDayInPeriod = Boolean(startValue && endValue && isBetween(day, startValue, endValue));
    var hasHoveredDay = hoveredDay !== null;
    var isDayInHoveredPeriod = hasHoveredDay && Boolean(focusInput === 'start' && endValue && isBetween(day, hoveredDay, endValue) || focusInput === 'end' && startValue && isBetween(day, startValue, hoveredDay));
    var hasLeftRoundings;
    var hasRightRoundings;
    if (hasHoveredDay) {
      var isDayBeforeFirstInPeriod = startValue ? isLess(hoveredDay, startValue) : endValue;
      var isDayAfterLastInPeriod = endValue ? isGreater(hoveredDay, endValue) : startValue;
      if (isDayFirst && (isGreaterOrEqual(hoveredDay, startValue) || focusInput === 'end')) {
        hasLeftRoundings = true;
      }
      if (isDayLast && (isLessOrEqual(hoveredDay, endValue) || focusInput === 'start')) {
        hasRightRoundings = true;
      }
      var isDayHovered = hoveredDay === day;
      if (isDayHovered) {
        if (isDayBeforeFirstInPeriod) {
          hasLeftRoundings = true;
        }
        if (isDayAfterLastInPeriod) {
          hasRightRoundings = true;
        }
      }
    } else {
      if (isDayFirst) {
        hasLeftRoundings = true;
      }
      if (isDayLast) {
        hasRightRoundings = true;
      }
    }
    var renderDayProps = _extends({}, props, (_extends2 = {}, _extends2[DayDateAttribute] = props.date, _extends2));
    var dataTid = null;
    if (isDayFirst) {
      dataTid = DateRangePickerDataTids.rangeStart;
    } else if (isDayLast) {
      dataTid = DateRangePickerDataTids.rangeEnd;
    }
    return /*#__PURE__*/(
      React.createElement("div", {
        className: cx(styles.rangeCalendarDay(), css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteralLoose(["\n              background: ", ";\n              border-top-left-radius: ", ";\n              border-bottom-left-radius: ", ";\n              border-top-right-radius: ", ";\n              border-bottom-right-radius: ", ";\n            "])), isDayInPeriod && t.rangeCalendarCellBg, hasLeftRoundings && t.calendarCellBorderRadius, hasLeftRoundings && t.calendarCellBorderRadius, hasRightRoundings && t.calendarCellBorderRadius, hasRightRoundings && t.calendarCellBorderRadius), (_cx4 = {}, _cx4[styles.rangeCalendarDayEnd(t)] = isDayFirst || isDayLast, _cx4[styles.rangeCalendarDayHoverInPeriod(t)] = isDayInPeriod, _cx4[styles.rangeCalendarDayInHoveredPeriod(t)] = isDayInHoveredPeriod, _cx4)),
        "data-tid": dataTid
      }, renderDayFn ? renderDayFn(renderDayProps) : /*#__PURE__*/React.createElement(CalendarDay, renderDayProps))
    );
  }
}));