import _extends from "@babel/runtime/helpers/esm/extends";
import { defaultLangCode, langCodesToCanonicalLocale } from "../../locale/constants";
import { defaultDateComponentsOrder, defaultDateComponentsSeparator, emptyDateComponents } from "../constants";
import { InternalDateCalculator } from "../InternalDateCalculator";
import { InternalDateGetter } from "../InternalDateGetter";
import { InternalDateSetter } from "../InternalDateSetter";
import { InternalDateTransformer } from "../InternalDateTransformer";
import { InternalDateValidator } from "../InternalDateValidator";
import { internalDateLocale } from "../localeSets";
import { InternalDateComponentType, InternalDateOrder, InternalDateValidateCheck, isInternalDateValidateCheck } from "../types";
var getRestoreYear = function getRestoreYear(prev, today) {
  if (prev.year !== null && InternalDateValidator.testParseToNumber(prev.year)) {
    if (prev.year > 50 && prev.year < 100) {
      return Number(prev.year) + 1900;
    } else if (prev.year > 0 && prev.year < 51) {
      return Number(prev.year) + 2000;
    }
    return prev.year;
  }
  return today.year;
};
export var InternalDate = /*#__PURE__*/function () {
  function InternalDate(_temp) {
    var _ref = _temp === void 0 ? {} : _temp,
      order = _ref.order,
      separator = _ref.separator,
      _ref$langCode = _ref.langCode,
      langCode = _ref$langCode === void 0 ? defaultLangCode : _ref$langCode,
      value = _ref.value;
    this.components = _extends({}, emptyDateComponents);
    this.canonicalLocale = 'ru-RU';
    this.start = null;
    this.end = null;
    this.order = order != null ? order : internalDateLocale[langCode].order;
    this.separator = separator != null ? separator : internalDateLocale[langCode].separator;
    this.canonicalLocale = langCodesToCanonicalLocale[langCode];
    if (value !== undefined) {
      this.parseInternalValue(value);
    }
  }
  var _proto = InternalDate.prototype;
  _proto.getComponentsRaw = function getComponentsRaw() {
    return _extends({}, this.components);
  };
  _proto.getComponentsLikeNumber = function getComponentsLikeNumber() {
    return InternalDateTransformer.dateComponentsStringToNumber(this.getComponentsRaw());
  };
  _proto.getSeparator = function getSeparator() {
    return this.separator;
  };
  _proto.getOrder = function getOrder() {
    return this.order;
  };
  _proto.getYear = function getYear() {
    return this.components.year;
  };
  _proto.getMonth = function getMonth() {
    return this.components.month;
  };
  _proto.getDate = function getDate() {
    return this.components.date;
  };
  _proto.getRangeStart = function getRangeStart() {
    return this.start;
  };
  _proto.getRangeEnd = function getRangeEnd() {
    return this.end;
  };
  _proto.setOrder = function setOrder(order) {
    if (order === void 0) {
      order = defaultDateComponentsOrder;
    }
    this.order = order;
    return this;
  };
  _proto.setSeparator = function setSeparator(separator) {
    if (separator === void 0) {
      separator = defaultDateComponentsSeparator;
    }
    this.separator = separator;
    return this;
  };
  _proto.setComponents = function setComponents(components, isNativeMonth) {
    if (isNativeMonth === void 0) {
      isNativeMonth = false;
    }
    if (components && isNativeMonth) {
      var clone = this.clone().setComponents(components).shiftMonth(1);
      if (clone.validate({
        checks: [InternalDateValidateCheck.Native]
      })) {
        this.components = _extends({}, clone.getComponentsLikeNumber());
      }
      return this;
    }
    this.components = components || _extends({}, emptyDateComponents);
    return this;
  };
  _proto.setYear = function setYear(year) {
    this.components.year = year;
    return this;
  };
  _proto.setMonth = function setMonth(month) {
    this.components.month = month;
    return this;
  };
  _proto.setDate = function setDate(date) {
    this.components.date = date;
    return this;
  };
  _proto.shiftYear = function shiftYear(step, _temp2) {
    var _ref2 = _temp2 === void 0 ? {} : _temp2,
      isLoop = _ref2.isLoop,
      isRange = _ref2.isRange,
      isCutFeb = _ref2.isCutFeb;
    var min = this.getMinValue(InternalDateComponentType.Year, isRange);
    var max = this.getMaxValue(InternalDateComponentType.Year, {
      isRange: isRange,
      isCutFeb: isCutFeb
    });
    var _this$getComponentsLi = this.getComponentsLikeNumber(),
      year = _this$getComponentsLi.year;
    this.components.year = InternalDateCalculator.calcShiftValueDateComponent(step, year, min, max, isLoop);
    return this;
  };
  _proto.shiftMonth = function shiftMonth(step, _temp3) {
    var _ref3 = _temp3 === void 0 ? {} : _temp3,
      isLoop = _ref3.isLoop,
      isRange = _ref3.isRange,
      isCutFeb = _ref3.isCutFeb;
    var min = this.getMinValue(InternalDateComponentType.Month, isRange);
    var max = this.getMaxValue(InternalDateComponentType.Month, {
      isRange: isRange,
      isCutFeb: isCutFeb
    });
    var _this$getComponentsLi2 = this.getComponentsLikeNumber(),
      month = _this$getComponentsLi2.month;
    this.components.month = InternalDateCalculator.calcShiftValueDateComponent(step, month, min, max, isLoop);
    return this;
  };
  _proto.shiftDate = function shiftDate(step, _temp4) {
    var _ref4 = _temp4 === void 0 ? {} : _temp4,
      isLoop = _ref4.isLoop,
      isRange = _ref4.isRange,
      isCutFeb = _ref4.isCutFeb;
    var min = this.getMinValue(InternalDateComponentType.Date, isRange);
    var max = this.getMaxValue(InternalDateComponentType.Date, {
      isRange: isRange,
      isCutFeb: isCutFeb
    });
    var _this$getComponentsLi3 = this.getComponentsLikeNumber(),
      date = _this$getComponentsLi3.date;
    this.components.date = InternalDateCalculator.calcShiftValueDateComponent(step, date, min, max, isLoop);
    return this;
  };
  _proto.setRangeStart = function setRangeStart(internalDate) {
    this.start = internalDate;
    return this;
  };
  _proto.setRangeEnd = function setRangeEnd(internalDate) {
    this.end = internalDate;
    return this;
  };
  _proto.get = function get(type) {
    return type !== null ? InternalDateGetter.getValueDateComponent(type, this.getComponentsRaw()) : null;
  };
  _proto.set = function set(type, value) {
    return type !== null ? InternalDateSetter.setValueDateComponent(this, type, value) : this;
  };
  _proto.shift = function shift(type, step, settings) {
    return type !== null ? InternalDateSetter.shiftValueDateComponent(this, type, step, settings) : this;
  };
  _proto.parseValue = function parseValue(value) {
    if (value === void 0) {
      value = '';
    }
    var components = InternalDateTransformer.parseValueToDate(value, this.order) || _extends({}, emptyDateComponents);
    this.setComponents(components);
    return this;
  };
  _proto.parseInternalValue = function parseInternalValue(value) {
    if (value === void 0) {
      value = '';
    }
    var components = InternalDateTransformer.parseValueToDate(value, InternalDateOrder.DMY) || _extends({}, emptyDateComponents);
    this.setComponents(components);
    return this;
  };
  _proto.validate = function validate(_temp5) {
    var _ref5 = _temp5 === void 0 ? {} : _temp5,
      type = _ref5.type,
      nextValue = _ref5.nextValue,
      _ref5$checks = _ref5.checks,
      checks = _ref5$checks === void 0 ? Object.values(InternalDateValidateCheck).filter(isInternalDateValidateCheck) : _ref5$checks;
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    var self = this;
    if (type !== undefined) {
      var clone = this.clone();
      if (nextValue !== undefined) {
        clone.set(type, nextValue);
      }
      self = clone;
    }
    if (checks.includes(InternalDateValidateCheck.NotNull) && !InternalDateValidator.checkForNull(self.getComponentsRaw(), type)) {
      return false;
    }
    if (checks.includes(InternalDateValidateCheck.Number) && !Object.values(self.getComponentsRaw()).every(InternalDateValidator.testParseToNumber)) {
      return false;
    }
    if (checks.includes(InternalDateValidateCheck.Limits) && !InternalDateValidator.checkLimits(self.getComponentsLikeNumber(), type)) {
      return false;
    }
    if (checks.includes(InternalDateValidateCheck.Native) && !InternalDateValidator.compareWithNativeDate(self.getComponentsLikeNumber())) {
      return false;
    }
    if (checks.includes(InternalDateValidateCheck.Range)) {
      return type !== undefined ? InternalDateValidator.checkRangePiecemeal(type, self.getComponentsLikeNumber(), self.start && self.start.getComponentsLikeNumber(), self.end && self.end.getComponentsLikeNumber()) : InternalDateValidator.checkRangeFully(self.toNumber(), self.start && self.start.toNumber(), self.end && self.end.toNumber());
    }
    return true;
  };
  _proto.toFragments = function toFragments(settings, components) {
    if (settings === void 0) {
      settings = {};
    }
    if (components === void 0) {
      components = this.getComponentsRaw();
    }
    return InternalDateTransformer.dateToFragments(components, _extends({
      order: this.order,
      separator: this.separator
    }, settings));
  }

  /**
   * Перевод даты в числовое представление (**НЕ** аналог `timestamp`)
   * Предназначено для быстрого сравнивания дат `<=>`
   */;
  _proto.toNumber = function toNumber() {
    return Number(this.toFragments({
      order: InternalDateOrder.YMD,
      withPad: true
    }).map(function (_ref6) {
      var valueWithPad = _ref6.valueWithPad;
      return valueWithPad;
    }).join(''));
  };
  _proto.toString = function toString(settings) {
    if (settings === void 0) {
      settings = {};
    }
    return this.toFragments(_extends({
      withPad: true,
      withSeparator: true
    }, settings)).filter(function (_ref7) {
      var value = _ref7.value;
      return value !== null;
    }).map(function (_ref8) {
      var type = _ref8.type,
        valueWithPad = _ref8.valueWithPad,
        value = _ref8.value;
      return settings.withPad && type !== InternalDateComponentType.Separator ? valueWithPad : value;
    }).join('');
  };
  _proto.toInternalString = function toInternalString() {
    return InternalDateTransformer.dateToInternalString(this.getComponentsRaw());
  };
  _proto.toNativeFormat = function toNativeFormat() {
    var components = this.getComponentsLikeNumber();
    if (InternalDateValidator.compareWithNativeDate(components)) {
      return _extends({}, components, {
        month: components.month - 1
      });
    }
    return undefined;
  };
  _proto.toA11YFormat = function toA11YFormat() {
    return InternalDateTransformer.componentsToA11YFormat(this.components, this.canonicalLocale);
  };
  _proto.clone = function clone() {
    return new InternalDate({
      order: this.order,
      separator: this.separator
    }).setComponents(_extends({}, this.components)).setRangeStart(this.start && this.start.clone()).setRangeEnd(this.end && this.end.clone());
  };
  _proto.duplicateOf = function duplicateOf(pattern) {
    return this.setComponents(pattern.getComponentsRaw());
  };
  _proto.restore = function restore(type) {
    if (type === void 0) {
      type = null;
    }
    var prev = this.getComponentsRaw();
    var today = InternalDateGetter.getTodayComponents();
    if (prev.year === null && prev.month === null && prev.date === null) {
      return this;
    }
    var restoreYear = getRestoreYear(prev, today);
    if (type === null && restoreYear !== prev.year || type === InternalDateComponentType.Year || type === InternalDateComponentType.All) {
      this.setYear(restoreYear);
    }
    if (type === null && prev.month === null || type === InternalDateComponentType.Month || type === InternalDateComponentType.All) {
      this.setMonth(today.month);
    }
    if (type === null && prev.date === null || type === InternalDateComponentType.Date || type === InternalDateComponentType.All) {
      this.setDate(today.date);
    }
    return this;
  };
  _proto.cutOffExcess = function cutOffExcess(type, _temp6) {
    if (type === void 0) {
      type = null;
    }
    var _ref9 = _temp6 === void 0 ? {} : _temp6,
      _ref9$isLoop = _ref9.isLoop,
      isLoop = _ref9$isLoop === void 0 ? false : _ref9$isLoop,
      isRange = _ref9.isRange,
      _ref9$isCutFeb = _ref9.isCutFeb,
      isCutFeb = _ref9$isCutFeb === void 0 ? false : _ref9$isCutFeb;
    var _this$components = this.components,
      year = _this$components.year,
      month = _this$components.month,
      date = _this$components.date;
    if ((type === null || type === InternalDateComponentType.Year) && InternalDateValidator.testParseToNumber(year)) {
      this.shiftYear(0, {
        isLoop: isLoop,
        isRange: isRange,
        isCutFeb: isCutFeb
      });
    }
    if ((type === null || type === InternalDateComponentType.Month) && InternalDateValidator.testParseToNumber(month)) {
      this.shiftMonth(0, {
        isLoop: isLoop,
        isRange: isRange,
        isCutFeb: isCutFeb
      });
    }
    if ((type === null || type === InternalDateComponentType.Date) && InternalDateValidator.testParseToNumber(date)) {
      this.shiftDate(0, {
        isLoop: isLoop,
        isRange: isRange,
        isCutFeb: isCutFeb
      });
    }
    return this;
  };
  _proto.isIncomplete = function isIncomplete() {
    return !this.isEmpty() && Object.values(this.components).some(function (component) {
      return component === null;
    });
  };
  _proto.isEmpty = function isEmpty() {
    return Object.values(this.components).every(function (component) {
      return component === null;
    });
  };
  _proto.isEqualComponentDate = function isEqualComponentDate(type, compared) {
    return this.get(type) === compared.get(type);
  };
  _proto.isEqual = function isEqual(compared) {
    return InternalDateValidator.isEqualDateValues(this, compared) && InternalDateValidator.isEqualDateFormats(this, compared);
  };
  _proto.getMinValue = function getMinValue(type, isRange) {
    if (isRange === true && this.start !== null) {
      return Number(InternalDateCalculator.calcRangeStartDateComponent(type, this.getComponentsLikeNumber(), this.start.getComponentsLikeNumber()));
    }
    return InternalDateGetter.getDefaultMin(type);
  };
  _proto.getMaxValue = function getMaxValue(type, _temp7) {
    var _ref10 = _temp7 === void 0 ? {} : _temp7,
      isRange = _ref10.isRange,
      isCutFeb = _ref10.isCutFeb;
    if (isRange && this.end !== null) {
      return Number(InternalDateCalculator.calcRangeEndDateComponent(type, this.getComponentsLikeNumber(), this.end.getComponentsLikeNumber()));
    }
    if (!isCutFeb) {
      return InternalDateGetter.getDefaultMax(type);
    }
    return InternalDateGetter.getDefaultMax(type, this.getComponentsLikeNumber());
  };
  return InternalDate;
}();