import isNumber from 'lodash/isNumber';
import isString from 'lodash/isString';
import isEmpty from 'lodash/isEmpty';

type TimeStamp = number;
export function shiftDateTo(date: Date | TimeStamp, days: number): Date {
  const ms = isNumber(date) ? date : date.getTime();
  return new Date(ms + getDaysInMs(days));
}

export function getDaysInMs(days: number): number {
  return days * 24 * 60 * 60 * 1000;
}

export function parseDateTime(isoDate: string, timezone = '+00:00'): Date {
  return new Date(isoDate.replace('Z', parseTimezone(timezone)));
}

export function parseTimezone(timezone: string): string {
  const matches = timezone.match(/^([+-]?)(\d{1,2})(?::(\d{1,2}))?$/);
  if (!matches) {
    return '';
  }
  let [d, hh, mm] = matches.slice(1);
  if (isEmpty(d)) {
    d = '+';
  }
  hh = hh.padStart(2, '0');
  mm = (mm || '').padStart(2, '0');

  return `${d}${hh}:${mm}`;
}

export function isDateValid(date: Date | string): boolean {
  if (isString(date)) {
    date = new Date(date);
  }
  return !isNaN(date.getTime());
}

enum TimeMeasure {
  'hour' = 3600,
  'minute' = 60,
  'secunde' = 1,
}

export function timeParse(timeString: string): number {
  const [hh, mm, ss] = timeString.split(':');
  const h = parseInt(hh, 10) * 3600;
  const m = parseInt(mm, 10) * 60;
  const s = parseInt(ss || '0', 10);

  return h + m + s;
}

/**
 * 
 * @param numberOfSecunds - Число секунд
 * @returns - Строка времени
 */
export function timeFormat(
  numberOfSecunds: number,
  format = 'hh:mm:ss'
): string {
  const h = Math.trunc(numberOfSecunds / 3600);
  const m = Math.trunc((numberOfSecunds % 3600) / 60);
  const s = (numberOfSecunds % 3600) % 60;

  return format
    .replace('hh', String(h).padStart(2, '0'))
    .replace('mm', String(m).padStart(2, '0'))
    .replace('ss', String(s).padStart(2, '0'));
}

/**
 *
 * @param time - Строка времени формата 00:00:00 или время в секундах
 * @param meadure - Еденицы измерения: часы, минуты или секунды
 * @param value - Прибавляемое значение
 * @returns - Время в секундах
 */
export function timeAdd(
  time: string | number,
  meadure: keyof typeof TimeMeasure,
  value: number
): number {
  time = isNumber(time) ? time : timeParse(time);
  return time + value * TimeMeasure[meadure];
}

/**
 *
 * @param time - Строка времени формата 00:00:00 или время в секундах 
 * @param meadure
 * @param value - Вычитаемое значение
 * @returns - Время в секундах
 */
export function timeSubs(
  time: string | number,
  meadure: keyof typeof TimeMeasure,
  value: number
): number {
  time = isNumber(time) ? time : timeParse(time);
  return time - value * TimeMeasure[meadure];
}

export function averageTime(
  time: string | number,
  meadure: keyof typeof TimeMeasure,
  value: number
): number {
  time = isNumber(time) ? time : timeParse(time);
  const coefficient = Math.trunc(time / (value * TimeMeasure[meadure]));
  return coefficient * (value * TimeMeasure[meadure]);
}
