import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import { parse, isValid, format, endOfMonth } from 'date-fns';
import { isNumber } from 'lodash-es';
import { RANGE_POSITION } from './const';

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
// TODO 国际化
function strictParse(string, pattern, backup) {
  const result = parse(string, pattern, backup);
  if (!isValid(result)) {
    return result;
  } else if (format(result, pattern) === string) {
    return result;
  } else {
    return new Date(Number.NaN);
  }
}
const isEmptyValue = val => {
  if (!val) {
    return true;
  }
  if (Array.isArray(val)) {
    return val.length === 0;
  }
  return false;
};

// FEATURE 以后时间相关的功能，都基于 date-fns 实现

function timeFormat(date) {
  let format = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'yyyy-MM-dd';
  if (!date) {
    return null;
  }
  if (isNumber(date)) {
    date = new Date(date);
  }
  const year = date.getFullYear();
  const month = date.getMonth();
  const day = date.getDate();
  const hours24 = date.getHours();
  const hours = hours24 % 12 === 0 ? 12 : hours24 % 12;
  const minutes = date.getMinutes();
  const seconds = date.getSeconds();
  const milliseconds = date.getMilliseconds();
  const dd = t => `0${t}`.slice(-2);
  const map = {
    yyyy: year,
    MM: dd(month + 1),
    MMMM: `${month + 1}月`,
    M: month + 1,
    dd: dd(day),
    d: day,
    HH: dd(hours24),
    H: hours24,
    hh: dd(hours),
    h: hours,
    mm: dd(minutes),
    m: minutes,
    ss: dd(seconds),
    s: seconds,
    S: milliseconds,
    Q: `Q${Math.floor(month / 3) + 1}`
  };
  return format.replace(/y+|M+|d+|H+|h+|m+|s+|S+|Q/g, str => String(map[str]));
}
const contrastDate = function (date1, date2) {
  let format = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'yyyy-MM-dd HH:mm:ss';
  const t1 = timeFormat(date1, format);
  const t2 = timeFormat(date2, format);
  if (t1 > t2) {
    return 1;
  }
  if (t1 === t2) {
    return 0;
  }
  return -1;
};
const parseDate = date => {
  const vDate = new Date(date || Date.now());
  return {
    year: vDate.getFullYear(),
    month: vDate.getMonth(),
    day: vDate.getDate(),
    hour: vDate.getHours(),
    minute: vDate.getMinutes(),
    second: vDate.getSeconds()
  };
};
const pickTime = dateObj => {
  return {
    hour: dateObj.hour,
    minute: dateObj.minute,
    second: dateObj.second
  };
};
function dateObjToDate(date) {
  var _date$month, _date$day2, _date$hour2, _date$minute2, _date$second2;
  let isFullMax = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  if (!date) {
    return null;
  }
  // 将季度转换为月份
  const month = (_date$month = date.month) !== null && _date$month !== void 0 ? _date$month : date.quarter ? (date.quarter - 1) * 3 : null;
  if (isFullMax) {
    var _date$month2, _date$day, _date$hour, _date$minute, _date$second;
    const month = (_date$month2 = date.month) !== null && _date$month2 !== void 0 ? _date$month2 : 11;
    const maxDay = new Date(date.year, month + 1, 0).getDate();
    return new Date(date.year, month !== null && month !== void 0 ? month : 11, (_date$day = date.day) !== null && _date$day !== void 0 ? _date$day : maxDay, (_date$hour = date.hour) !== null && _date$hour !== void 0 ? _date$hour : 23, (_date$minute = date.minute) !== null && _date$minute !== void 0 ? _date$minute : 59, (_date$second = date.second) !== null && _date$second !== void 0 ? _date$second : 59, 999);
  }
  return new Date(date.year, month !== null && month !== void 0 ? month : 0, (_date$day2 = date.day) !== null && _date$day2 !== void 0 ? _date$day2 : 1, (_date$hour2 = date.hour) !== null && _date$hour2 !== void 0 ? _date$hour2 : 0, (_date$minute2 = date.minute) !== null && _date$minute2 !== void 0 ? _date$minute2 : 0, (_date$second2 = date.second) !== null && _date$second2 !== void 0 ? _date$second2 : 0, 0);
}
function transformDateToTimestamp(date) {
  let isFullMax = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  if (!date) {
    return null;
  }
  return dateObjToDate(date, isFullMax).getTime();
}
const padStartZero = function (target) {
  let len = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
  return `${target}`.padStart(len, '0');
};
const getTimestampFromFormat = (date, format, isFullMax) => {
  date = date || new Date();
  const dateObj = {
    year: date.getFullYear()
  };
  if (/M/.test(format)) {
    dateObj.month = date.getMonth();
  }
  if (/d/.test(format)) {
    dateObj.day = date.getDate();
  }
  if (/H/.test(format)) {
    dateObj.hour = date.getHours();
  }
  if (/m/.test(format)) {
    dateObj.minute = date.getMinutes();
  }
  if (/s/.test(format)) {
    dateObj.second = date.getSeconds();
  }
  if (/Q/.test(format)) {
    dateObj.quarter = Math.floor(date.getMonth() / 3) + 1;
  }
  return transformDateToTimestamp(dateObj, isFullMax);
};
const transformTimeToDate = timeStr => {
  if (!/^\d{1,2}:\d{1,2}:\d{1,2}$/.test(timeStr)) {
    console.warn(`[fes-date-picker] defaultTime format expect: HH:mm:ss，now is ${timeStr}`);
    timeStr = '00:00:00';
  }
  const times = timeStr.split(':');
  return {
    hour: Number(times[0]),
    minute: Number(times[1]),
    second: Number(times[2])
  };
};
const fillDate = _ref => {
  let {
    dateObj,
    format,
    defaultTime,
    rangePosition
  } = _ref;
  const newDateObj = _objectSpread({}, dateObj);

  // FEATURE 支持填充其他格式
  if (!/d/.test(format)) {
    if (rangePosition === RANGE_POSITION.LEFT) {
      newDateObj.day = 1;
    } else {
      const date = dateObjToDate(dateObj);
      newDateObj.day = endOfMonth(date).getDate();
    }
  }
  return _objectSpread(_objectSpread({}, newDateObj), getDefaultTime(defaultTime, rangePosition));
};
const getDefaultTime = (defaultTime, rangePosition, hasTime) => {
  const time = {};
  if (typeof defaultTime === 'string') {
    Object.assign(time, transformTimeToDate(defaultTime));
  } else if (Array.isArray(defaultTime)) {
    if (rangePosition === RANGE_POSITION.LEFT) {
      Object.assign(time, transformTimeToDate(defaultTime[0]));
    } else {
      Object.assign(time, transformTimeToDate(defaultTime[1]));
    }
  } else if (!rangePosition && hasTime) {
    const date = new Date();
    time.hour = date.getHours();
    time.minute = date.getMinutes();
    time.second = date.getSeconds();
  } else if (rangePosition === RANGE_POSITION.RIGHT) {
    time.hour = 23;
    time.minute = 59;
    time.second = 59;
  } else {
    time.hour = 0;
    time.minute = 0;
    time.second = 0;
  }
  return time;
};
const isBeyondRangeTime = option => {
  if (!option.flagDate || !option.maxRange) {
    return false;
  }
  const arr = option.maxRange.match(/(\d*)([MDY])/);
  const length = Number(arr[1]);
  const type = arr[2];
  let minDate;
  let maxDate;
  if (type === 'D') {
    // FEATURE: 后续采取 unicode token 标准(https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)，用 d
    minDate = new Date(option.flagDate);
    maxDate = new Date(option.flagDate);
    minDate.setDate(minDate.getDate() - length + 1);
    maxDate.setDate(maxDate.getDate() + length - 1);
  } else if (type === 'M') {
    // DEPRECATED 后续废弃对 M 和 Y 的支持
    minDate = new Date(option.flagDate);
    maxDate = new Date(option.flagDate);
    minDate.setMonth(minDate.getMonth() - length, maxDate.getDate() + 1);
    maxDate.setMonth(maxDate.getMonth() + length, maxDate.getDate() - 1);
  } else if (type === 'Y') {
    // FEATURE: 后续采取 unicode token 标准，用 y
    minDate = new Date(option.flagDate.getFullYear() + length, 0);
    maxDate = new Date(option.flagDate.getFullYear() - length, 0);
  }
  if (!(minDate || maxDate)) {
    return false;
  }
  return contrastDate(option.currentDate, minDate, option.format) === -1 || contrastDate(option.currentDate, maxDate, option.format) === 1;
};

export { contrastDate, dateObjToDate, fillDate, getDefaultTime, getTimestampFromFormat, isBeyondRangeTime, isEmptyValue, padStartZero, parseDate, pickTime, strictParse, timeFormat, transformDateToTimestamp, transformTimeToDate };
