import { __read } from "tslib";
import React, { useRef, useState, useMemo, useEffect } from "react";
import Calendar from "../Calendar/Calendar";
import { ISO8601, formatISO8601ToDate } from "../utils/date";
import { useOnClickOutside } from "../hooks/useOnClickOutside";
import createAutoCorrectedDatePipe from "./createAutoCorrectedDatePipe";
import { MountedState } from "./interfaces";
import { datePattern, ErrorRangeDateMsg, ErrorValidateDateMsg, DateEndPlaceholder, DateStartPlaceholder, PlaceholderChar } from "./constants";
import { DatePickerWrapper, CalendarWrapper, InputDateWrapper, StyledInputDate, Error } from "./styles";
var InputDate = function (_a) {
    var id = _a.id, idCalendar = _a.idCalendar, _b = _a.locale, locale = _b === void 0 ? "ru" : _b, _c = _a.isRangeMode, isRangeMode = _c === void 0 ? false : _c, onChange = _a.onChange, placeholder = _a.placeholder, _d = _a.maxDate, maxDate = _d === void 0 ? "31.12.2050" : _d, _e = _a.minDate, minDate = _e === void 0 ? "01.01.1920" : _e, onKeyDown = _a.onKeyDown, _f = _a.isShowMask, isShowMaskProps = _f === void 0 ? false : _f, className = _a.className, _g = _a.value, value = _g === void 0 ? "" : _g, onCalendarClose = _a.onCalendarClose, onCalendarOpen = _a.onCalendarOpen, onDateSelected = _a.onDateSelected, _h = _a.placeholderChar, placeholderChar = _h === void 0 ? PlaceholderChar : _h, onBlur = _a.onBlur, onFocus = _a.onFocus, isDisabled = _a.isDisabled, inputError = _a.error, _j = _a.testId, testId = _j === void 0 ? "inputDate" : _j, width = _a.width, status = _a.status, size = _a.size, statusText = _a.statusText, isRequired = _a.isRequired, isShowClearIcon = _a.isShowClearIcon, iconLeft = _a.iconLeft, iconRight = _a.iconRight, isReadOnly = _a.isReadOnly, viewType = _a.viewType, onClear = _a.onClear;
    var datePickerRef = useRef(null);
    var _k = __read(useState(false), 2), isCalendarShown = _k[0], setCalendarShown = _k[1];
    var _l = __read(useState(value), 2), currentDate = _l[0], setCurrentDate = _l[1];
    var _m = __read(useState(inputError), 2), error = _m[0], setError = _m[1];
    var _o = __read(useState(isShowMaskProps), 2), isShowMask = _o[0], setShowMask = _o[1];
    var minimalDate = useMemo(function () { return formatISO8601ToDate(minDate); }, [minDate]);
    var maximalDate = useMemo(function () { return formatISO8601ToDate(maxDate); }, [maxDate]);
    var autoCorrectedDatePipe = useMemo(function () { return createAutoCorrectedDatePipe(ISO8601, {}); }, []);
    var mounted = useMemo(function () { return ({ current: MountedState.BEFORE }); }, []);
    var mountedState = mounted.current;
    var onDateChange = function (_value) {
        setCurrentDate(_value);
        onChange === null || onChange === void 0 ? void 0 : onChange(_value);
    };
    var closeCalendarAndResetDate = function () {
        setCalendarShown(false);
        handleSelected();
    };
    var checkErrors = function (date) {
        if (isRangeMode && !checkValidDateRange(date)) {
            setError(ErrorRangeDateMsg);
        }
        else if (!isRangeMode && !checkValidDate(date)) {
            setError(ErrorValidateDateMsg);
        }
        else {
            setError(undefined);
        }
    };
    var handleSettingDateToInputFromCalendar = function (date) {
        if (isRangeMode) {
            setDateRangeToInput(date);
        }
        else if (date !== currentDate) {
            checkErrors(date);
            setCurrentDate(date);
            onChange === null || onChange === void 0 ? void 0 : onChange(date);
            checkValidDate(date) && (onDateSelected === null || onDateSelected === void 0 ? void 0 : onDateSelected(date));
        }
    };
    var setDateRangeToInput = function (date) {
        var _a = __read(currentDate.split(" / "), 2), rangeDateStart = _a[0], rangeDateEnd = _a[1];
        var dateStart = rangeDateStart || DateStartPlaceholder;
        var dateEnd = rangeDateEnd || DateStartPlaceholder;
        if (datePattern.test(dateStart) && datePattern.test(dateEnd)) {
            setCurrentDate(date + DateEndPlaceholder);
        }
        else if (datePattern.test(dateStart)) {
            var dateRange = dateStart + " / " + date;
            var currentDateRange = checkValidDateRange(dateRange)
                ? dateRange
                : date + " / " + dateStart;
            checkErrors(currentDateRange);
            setCurrentDate(currentDateRange);
            onChange === null || onChange === void 0 ? void 0 : onChange(currentDateRange);
        }
        else {
            setCurrentDate(date + " / " + dateEnd);
            onChange === null || onChange === void 0 ? void 0 : onChange(date + " / " + dateEnd);
        }
    };
    var checkValidDate = function (date) {
        if (datePattern.test(date)) {
            var dateInISO = formatISO8601ToDate(date);
            var isMinimalDateValid = minimalDate === undefined || minimalDate <= dateInISO;
            var isMaximalDateValid = maximalDate === undefined || maximalDate >= dateInISO;
            return isMinimalDateValid && isMaximalDateValid;
        }
        return false;
    };
    var checkValidDateRange = function (date) {
        var _a = __read(date.split(" / "), 2), dateStart = _a[0], dateEnd = _a[1];
        if (!datePattern.test(dateStart) && !datePattern.test(dateEnd)) {
            return false;
        }
        var dateStartISO = formatISO8601ToDate(dateStart);
        var dateEndISO = formatISO8601ToDate(dateEnd);
        if (!checkValidDate(dateStart) || !checkValidDate(dateEnd)) {
            setError(ErrorValidateDateMsg);
            return false;
        }
        else {
            setError(undefined);
        }
        if (dateStartISO > dateEndISO) {
            setError(ErrorRangeDateMsg);
        }
        return dateStartISO <= dateEndISO;
    };
    var handleKeyDown = function (event) {
        if (event.key === "Escape") {
            closeCalendarAndResetDate();
        }
        if (event.key === "Enter") {
            if ((isRangeMode && checkValidDateRange(currentDate)) ||
                (!isRangeMode && checkValidDate(currentDate))) {
                checkErrors(currentDate);
                value !== currentDate && (onDateSelected === null || onDateSelected === void 0 ? void 0 : onDateSelected(currentDate));
            }
        }
        onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
    };
    var handleFocus = function (event) {
        setShowMask(true);
        onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
    };
    var handleBlur = function () {
        setShowMask(false);
        handleSelected();
        onBlur === null || onBlur === void 0 ? void 0 : onBlur();
    };
    var handleCloseCalendar = function () {
        setCalendarShown(false);
        value !== currentDate && handleSelected();
    };
    var handleSelected = function () {
        if (isRangeMode) {
            !checkValidDateRange(currentDate) && setCurrentDate(value);
            !checkValidDateRange(currentDate) && (onDateSelected === null || onDateSelected === void 0 ? void 0 : onDateSelected(value));
        }
        else {
            checkErrors(currentDate);
            !checkValidDate(currentDate) && setCurrentDate(value);
            !checkValidDate(currentDate) && (onDateSelected === null || onDateSelected === void 0 ? void 0 : onDateSelected(value));
        }
    };
    useEffect(function () {
        if (mountedState === MountedState.BEFORE) {
            mounted.current = MountedState.CURRENT;
        }
        else {
            mounted.current = MountedState.AFTER;
        }
    });
    useEffect(function () {
        if (isCalendarShown) {
            onCalendarOpen === null || onCalendarOpen === void 0 ? void 0 : onCalendarOpen();
        }
        else {
            onCalendarClose === null || onCalendarClose === void 0 ? void 0 : onCalendarClose();
        }
    }, [isCalendarShown]);
    useEffect(function () {
        setCurrentDate(value);
    }, [value]);
    useEffect(function () {
        setShowMask(isShowMask);
    }, [isShowMask]);
    useEffect(function () {
        var _a = __read(currentDate.split(" / "), 2), dateStart = _a[0], dateEnd = _a[1];
        if (datePattern.test(dateStart) && datePattern.test(dateEnd)) {
            handleCloseCalendar();
        }
    }, [currentDate]);
    useOnClickOutside(datePickerRef, closeCalendarAndResetDate, isCalendarShown);
    return (React.createElement(DatePickerWrapper, { width: width, className: className, ref: datePickerRef },
        React.createElement(InputDateWrapper, null,
            React.createElement(StyledInputDate, { className: className, testId: testId, id: id, isCalendarShown: isCalendarShown, pipe: autoCorrectedDatePipe, placeholder: placeholder, isRangeMode: isRangeMode, toggleCalendar: function () { return setCalendarShown(!isCalendarShown); }, onDateChange: onDateChange, value: currentDate, isDisabled: isDisabled, onKeyDown: handleKeyDown, onBlur: handleBlur, onFocus: handleFocus, isGuide: true, isShowMask: isShowMask, isKeepCharPositions: true, type: "tel", placeholderChar: placeholderChar, width: width, statusText: statusText, isRequired: isRequired, isShowClearIcon: isShowClearIcon, status: status, size: size, iconLeft: iconLeft, iconRight: iconRight, isReadOnly: isReadOnly, viewType: viewType, onClear: onClear })),
        isCalendarShown && (React.createElement(CalendarWrapper, null,
            React.createElement(Calendar, { id: idCalendar, minDate: minDate, maxDate: maxDate, locale: locale, isRangeMode: isRangeMode, closeCalendar: handleCloseCalendar, date: value, setDateToInput: handleSettingDateToInputFromCalendar }))),
        typeof error === "string" && !!error.trim() && (React.createElement(Error, { type: "pavo", "data-element": "input-error", "data-testid": testId + "_errorCheck" }, error))));
};
export default InputDate;
