import moment from 'moment';

export default class WsDatePickerService {
  serverDateFormat
  WEEKENDS_ISO
  DAYS_IN_A_MONTH

  constructor() {
    this.serverDateFormat = 'YYYY-MM-DD';
    this.WEEKENDS_ISO = [6, 7];
    this.DAYS_IN_A_MONTH = 30;
  }

  getYesterdayDateAsString = function getYesterdayDateAsString() {
    const minDate = new Date();
    minDate.setDate(minDate.getDate() - 1);
    return minDate.toString();
  }

  getCurrentDateAsString = function getCurrentDateAsString() {
    return new Date().toString();
  }

  getNextYearDateAsString = function getNextYearDateAsString() {
    const maxDate = new Date();
    maxDate.setFullYear(maxDate.getFullYear() + 1);
    return maxDate.toString();
  }

  getCalendarEndDate = function getCalendarEndDate() {
    return moment().endOf('year');
  }

  getCalendarEndDateAsString() {
    return this.getCalendarEndDate().toString();
  }

  getFutureDate = function getFutureDate(numbDays) {
    return moment().add(numbDays, 'day');
  }

  getFutureDateAsString(numbDays) {
    return this.getFutureDate(numbDays).toString();
  }

  _isDateAvailable = function _isDateAvailable(disabledDates, date) {
    if (!disabledDates || !disabledDates.includes(date)) {
      return true;
    }
    return false;
  }

  getCurrentDateAsServerString() {
    return moment().format(this.serverDateFormat);
  }

  convertDisplayInputDateToServerFormat(displayInputDateString) {
    const date = new Date(displayInputDateString);
    return moment(date).format(this.serverDateFormat);
  }

  _isWeekend(date) {
    const day = date.isoWeekday();
    return day && this.WEEKENDS_ISO.includes(day);
  }

  getDatesFromNowToN(n, onlyBusinessDays = false) {
    const aryDates = [];
    let daysToAdd = n;
    let daysInFuture = 0;
    while (daysToAdd >= 0) {
      const futureDate = this.getFutureDate(daysInFuture);
      if (onlyBusinessDays && !this._isWeekend(futureDate)) {
        --daysToAdd;
      } else if (!onlyBusinessDays) {
        --daysToAdd;
      }
      aryDates.push(futureDate.format('YYYY/MM/DD'));
      ++daysInFuture;
    }
    return aryDates;
  }

  getWeekendDates(startDate, endDate) {
    const start = moment(new Date(startDate));
    const end = moment(new Date(endDate));
    const weekendDates = [];
    const iterator = moment(start);
    while (iterator <= end) {
      this.WEEKENDS_ISO.forEach((weekendDay) => {
        iterator.isoWeekday(weekendDay);
        if (iterator >= start && iterator <= end) {
          weekendDates.push(iterator.format('YYYY/MM/DD'));
        }
      });
      iterator.add(1, 'day');
    }
    return weekendDates;
  }

  getNextAvailableDate(disabledDates, preferredDate = moment()) {
    if (preferredDate && this._isDateAvailable(disabledDates, preferredDate.format('YYYY/MM/DD'))) {
      return preferredDate.toString();
    }
    for (let i = 0; i < this.DAYS_IN_A_MONTH; i++) {
      if (this._isDateAvailable(disabledDates,
        this.getFutureDate(i).format('YYYY/MM/DD'))) {
        return this.getFutureDateAsString(i);
      }
    }
    return null;
  }
}
