utils/common.js

/* eslint-disable operator-assignment */
/* eslint-disable no-param-reassign */
/* eslint-disable no-restricted-globals */
/**
 * @namespace utils/common
 */

// eslint-disable-next-line import/no-cycle
import { MENU_ITEMS, COUNTRY_TIMEZONE } from '../constants';

/**
 * Parse date in format DD/MM/YY
 *
 * @memberof utils/common
 * @param {Time} dateString
 * @example 2020-04-27T09:18:02Z
 * parsed to   "27 / 04 / 20"
 * @returns {string} Parsed date and time
 */
export function getDate(dateString) {
  if (dateString) {
    const dateTime = dateString.split('T');
    const date = dateTime[0].split('-');
    return `${date[2]} / ${date[1]} / ${date[0][2]}${date[0][3]}`;
  }
  return '';
}
/**
 * Parse date in format DD/MM/YYYY, time in format hh:mm:ss
 *
 * @memberof utils/common
 * @param {Time} dateString
 * @example 2020-04-27T09:18:02Z
 * parsed to   "27/04/2020 09:18:02"
 * @returns {string} Parsed date and time
 */
export function getDateTime(dateString) {
  if (dateString) {
    const dateTime = dateString.split('T');
    const date = dateTime[0].split('-');
    const time = dateTime[1].split('.')[0].split(':');
    return `${date[2]}/${date[1]}/${date[0]} ${time[0]}:${time[1]}:${time[2]}`;
  }
  return '';
}
/**
 * Parse date in format DD/MM/YYYY, time in format hh:mm:ss with time zone
 *
 * @memberof utils/common
 * @param {Time} dateString
 * @example 2020-04-27T09:18:02Z
 * parsed to   "27/04/2020 09:18:02"
 * @returns {string} Parsed date and time
 */
export function getDateTimeWithUserTimezone(dateString) {
  if (dateString) {
    const timeZonediff = new Date(dateString).getTimezoneOffset();
    const newDateStr = new Date(dateString).toISOString().slice(0, 19).replace('T', ' ');
    const jsDate = new Date(newDateStr.replace(/-/g, '/'));
    const fullDate = new Date(jsDate.getTime() - timeZonediff * 60000 - timeZonediff * 60000);
    const newDate = `${fullDate.getDate()}`.padStart(2, '0');
    const newMonth = `${fullDate.getMonth() + 1}`.padStart(2, '0');
    const newHours = `${fullDate.getHours()}`.padStart(2, '0');
    const newMinutes = `${fullDate.getMinutes()}`.padStart(2, '0');
    const newSeconds = `${fullDate.getSeconds()}`.padStart(2, '0');
    return `${newDate}/${newMonth}/${fullDate.getFullYear()} ${newHours}:${newMinutes}:${newSeconds}`;
  }
  return '';
}
/**
 * Parse date in format YYYY/MM/DD
 *
 * @memberof utils/common
 * @param {Time} date
 * @example new Date()
 * parsed to   "17/05/2020"
 * @returns {string}
 */
export function getDateForCalendar(date) {
  if (date) {
    let month = date.getMonth() + 1;
    month = month < 10 ? `0${month}` : month;
    let day = date.getDate();
    day = day < 10 ? `0${day}` : day;
    return `${day}/${month}/${date.getFullYear()}`;
  }
  return '';
}
/**
 * Parse date in format YYYY-MM-DD
 *
 * @memberof utils/common
 * @param {Time} date
 * @example new Date()
 * parsed to   "2020-05-07"
 * @returns {string}
 */
export function getDateForFilter(date) {
  if (date) {
    let month = date.getMonth() + 1;
    month = month < 10 ? `0${month}` : month;
    let day = date.getDate();
    day = day < 10 ? `0${day}` : day;
    return `${date.getFullYear()}-${month}-${day}`;
  }
  return '';
}
/**
 * Parse date in format YYYY-MM-DD
 *
 * @memberof utils/common
 * @param {string} date
 * @example "07/05/2020"
 * parsed to   "2020-05-07"
 * @returns {string}
 */
export function getDateFromString(date) {
  if (date) {
    const dates = date.split('/');
    return `${dates[2]}-${dates[1]}-${dates[0]}`;
  }
  return '';
}
/**
 * Parse date in format YYYY-MM-DD hh:mm
 *
 * @memberof utils/common
 * @param {Time} date
 * @example new Date()
 * parsed to   "2020-05-07 23:59"
 * @returns {string}
 */
export function getDateForIntervalFilter(date) {
  if (date) {
    let month = date.getMonth() + 1;
    month = month < 10 ? `0${month}` : month;
    let day = date.getDate();
    day = day < 10 ? `0${day}` : day;
    let hour = date.getHours();
    hour = hour < 10 ? `0${hour}` : hour;
    let minute = date.getMinutes();
    minute = minute < 10 ? `0${minute}` : minute;
    return `${date.getFullYear()}-${month}-${day} ${hour}:${minute}`;
  }
  return '';
}
/**
 * Parse date in format DD/MM/YYYY, time in format hh:mm:ss with selected country time zone
 *
 * @memberof utils/common
 * @param {Time} dateString
 * @param {string} selectedTimezone
 * @example 2020-04-27T09:18:02Z
 * parsed to   "27/04/2020 09:18:02"
 * @returns {string} Parsed date and time
 */
export function getCountryDateTime(dateString, selectedTimezone) {
  if (dateString) {
    const timezone = selectedTimezone ? selectedTimezone.name : COUNTRY_TIMEZONE[process.env.BUNDLE_SKIN];
    const offset = new Date().getTimezoneOffset();
    const localDateTime = new Date(dateString.replace(/z/gi, '')).setMinutes(
      new Date(dateString).getMinutes() - offset
    );
    const dateTime = new Date(localDateTime).toLocaleString('en-GB', { timeZone: timezone });
    return dateTime.replace(',', ' ');
  }
  return '';
}

/**
 * Parse date in format DD/MM/YYYY, with selected country time zone
 *
 * @memberof utils/common
 * @param {Time} dateString
 * @param {string} selectedTimezone
 * @example 2020-04-27T09:18:02Z
 * parsed to   "27/04/2020"
 * @returns {string}
 */
export function getCountryDate(dateString, selectedTimezone) {
  if (dateString) {
    const dateAndTime = getCountryDateTime(dateString, selectedTimezone);
    const [date] = dateAndTime.split(' ');
    return date;
  }
  return '';
}

/**
 * get offset depending on selected timezone
 *
 * @memberof utils/common
 * @param {object} selectedTimezone
 * @returns {integer} offset
 */
export function getOffsetByTimezone(selectedTimezone) {
  const timezone =
    selectedTimezone && typeof selectedTimezone === 'object'
      ? selectedTimezone.name
      : COUNTRY_TIMEZONE[process.env.BUNDLE_SKIN];
  const a = new Date().toLocaleString('ja', { timeZone: timezone }).split(/[/\s:]/);
  a[1] -= 1;
  const t1 = Date.UTC.apply(null, a);
  const t2 = new Date().setMilliseconds(0);
  return (t1 - t2) / 60 / 1000;
}
/**
 * get javascript date object in nigeria time
 *
 * @memberof utils/common
 * @param {string} selectedTimezone
 * @param {Time} date
 * @returns {Date} Parsed date and time
 */
export function getCountryNewDate(selectedTimezone, date) {
  const offset = new Date().getTimezoneOffset();
  const countryOffset = offset + getOffsetByTimezone(selectedTimezone);
  const ngdate = date ? new Date(date) : new Date();
  return new Date(
    Date.UTC(
      ngdate.getUTCFullYear(),
      ngdate.getUTCMonth(),
      ngdate.getUTCDate(),
      ngdate.getUTCHours(),
      ngdate.getUTCMinutes() + countryOffset,
      ngdate.getUTCSeconds()
    )
  );
}
/**
 * get javascript date object in utc time from country time
 *
 * @memberof utils/common
 * @param {string} countryOffset
 * @param {Time} date
 * @example 2020-04-27T09:18:02Z
 * parsed to   "27/04/2020 09:18:02"
 * @returns {string} Parsed date and time
 */
export function getUCTDateFromCountryDate(countryOffset, date) {
  return new Date(date).setMinutes(new Date(date).getMinutes() - countryOffset);
}
/**
 * get UTC string date
 *
 * @memberof utils/common
 * @param {object} payload
 * @returns {string} utc date time
 */
export function getFilterUTCDate(payload) {
  const filter = payload.filter;
  const filterFields = payload.filterFields;
  const keys = payload.keys;
  const newUTCfilter = {};
  const contryOffset = getOffsetByTimezone(payload.selectedTimezone);
  if (payload.keys) {
    keys.map((k) => {
      if (filter[k] && filterFields.find((f) => f.fields && f.fields.includes(k))) {
        const utcDateStr = getDateForIntervalFilter(new Date(getUCTDateFromCountryDate(contryOffset, filter[k])));
        newUTCfilter[k] = utcDateStr.toString().replace(/ /g, 'T');
      } else {
        newUTCfilter[k] = filter[k];
      }
    });
  }
  return newUTCfilter || null;
}
/**
 * Get day before today
 *
 * @memberof utils/common
 * @param {object} selectedTimezone
 * @returns {Time}
 */
export function getYesterday(selectedTimezone) {
  const yesterday = getCountryNewDate(selectedTimezone);
  yesterday.setDate(yesterday.getDate() - 1);

  return yesterday;
}

/**
 * Get today
 *
 * @memberof utils/common
 * @param {object} selectedTimezone
 * @returns {Time}
 */
export function getToday(selectedTimezone) {
  return getCountryNewDate(getOffsetByTimezone(selectedTimezone));
}

/**
 * @constant
 */
const MONTH_NAMES = [
  'January',
  'February',
  'March',
  'April',
  'May',
  'June',
  'July',
  'August',
  'September',
  'October',
  'November',
  'December',
];
/**
 * Get Month in format mm YYYY
 *
 * @memberof utils/common
 * @example new Date()
 * parsed to April 2020
 * @param {Time} date
 * @returns {Time}
 */
export function getMonth(date) {
  return `${MONTH_NAMES[date.getMonth()]} ${date.getFullYear()}`;
}
/**
 * Parse amounts
 *
 * @memberof utils/common
 * @param {number} value
 * @param {number} divider
 * @example parseAmount(5000000,1)
 * parsed to   "5,000,000.00"
 * or parseAmount(5000000,100)
 * parsed to   "50,000.00"
 * @returns {string}
 */
export function parseAmount(value, divider) {
  return value ? (value / divider).toFixed(2).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') : '0.00';
}
/**
 * Parse points
 *
 * @memberof utils/common
 * @param {number} value
 * @param {char} sign
 * @example parsePoints(5000000,'.')
 * parsed to   "5.000.000"
 * @returns {string}
 */
export function parsePoints(value, sign) {
  return value ? value.toFixed(0).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, `$1${sign}`) : 0;
}
/**
 * Parse float
 *
 * @memberof utils/common
 * @param {number} value
 * @param {number} divider
 * @example parseDecimal(5000000)
 * parsed to   "50000.00"
 * @returns {string}
 */
export function parseDecimal(value, divider) {
  return value ? parseFloat(value / divider).toFixed(2) : '0.00';
}

/**
 * Parse points object into array
 *
 * @memberof utils/common
 * @param {object} pointsObject
 * @returns {Array}
 */
export function parsePointsSettings(pointsObject) {
  const points = [];
  Object.keys(pointsObject).map((key, i) => {
    const point = {};
    Object.keys(pointsObject[key]).map((p) => {
      point[p] = pointsObject[key][p] * 100;
    });
    points.push({
      selectionIndex: i + 1,
      ...point,
    });
  });
  return points;
}
/**
 * Parse points array into object to sent data to API
 *
 * @memberof utils/common
 * @param {Array} pointsArray
 * @returns {object}
 */
export function revertPointsSettingsIntoObject(pointsArray) {
  const points = {};
  pointsArray.map((p, i) => {
    const point = { ...p };
    delete point.edited;
    delete point.selectionIndex;
    Object.keys(point).map((key) => {
      point[key] = point[key] / 100;
    });
    points[i + 1] = point;
  });
  return points;
}

/**
 * Parse bonus time allowed string
 *
 * @memberof utils/common
 * @param {Array} bonusSettings
 * @returns {Array}
 */
export function parseBonusSettings(bonusSettings) {
  bonusSettings.map((bonus) => {
    const length = bonus.timeAllowed.length;
    let selection;
    let start = 1;
    switch (bonus.timeAllowed[length - 1]) {
      case 'D':
        selection = 'days';
        break;
      case 'H':
        start = 2;
        selection = 'hours';
        break;
      case 'W':
        selection = 'weeks';
        break;
      case 'M':
        selection = 'months';
        break;
      case 'Y':
        selection = 'years';
        break;
      default:
        break;
    }
    bonus.time = bonus.timeAllowed.slice(start, length - 1);
    bonus.selection = selection;
  });
  return bonusSettings;
}

/**
 * Parse bonus time allowed string to sent data to API
 *
 * @memberof utils/common
 * @param {Array} bonusSettings
 * @returns {Array}
 */
export function revertBonusSettings(bonusSettings) {
  bonusSettings.map((bonus) => {
    let selection;
    let start = 'P';
    switch (bonus.selection) {
      case 'days':
        selection = 'D';
        break;
      case 'hours':
        start = 'PT';
        selection = 'H';
        break;
      case 'weeks':
        selection = 'W';
        break;
      case 'months':
        selection = 'M';
        break;
      case 'years':
        selection = 'Y';
        break;
      default:
        break;
    }
    bonus.timeAllowed = `${start}${bonus.time}${selection}`;
  });
  return bonusSettings;
}

/**
 * Month here is 1-indexed (January is 1, February is 2, etc). This is
 * because we're using 0 as the day so that it returns the last day
 * of the last month, so you have to add 1 to the month number
 * so it returns the correct amount of days
 *
 * @memberof utils/common
 * @param {number} month
 * @param {number} year
 * @returns {number}
 */
export function daysInMonth(month, year) {
  return new Date(year, month, 0).getDate();
}
/**
 * Return index of day in week
 *
 * @memberof utils/common
 * @param {number} month
 * @param {number} year
 * @returns {number}
 */
export function weekDayInMonth(month, year) {
  return new Date(year, month, 1).getDay();
}

/**
 * Parse round details response
 *
 * @memberof utils/common
 * @param {object} roundDetails
 * @returns {object}
 */
export function parseRoundDetails(roundDetails) {
  const newRoundDetails = {
    leagues: [],
    matches: [],
    roundId: roundDetails.roundId,
  };

  roundDetails.competitionNames.map((name, i) => {
    const rsResults = roundDetails.roundSpecialResults?.[i]?.split('|');
    const roundSpecialResults = {};
    rsResults?.forEach((result) => {
      const resultInfo = result?.split(':');
      roundSpecialResults[resultInfo[0]] = resultInfo[1];
    });
    const ggResults = roundDetails.extraResults?.[i]?.split('|');
    const goalGaloreResults = {};
    ggResults?.forEach((result) => {
      const resultInfo = result?.split(':');
      goalGaloreResults[resultInfo[0]] = resultInfo[1];
    });

    newRoundDetails.leagues.push({ name, id: roundDetails.competitions[i], roundSpecialResults, goalGaloreResults });
  });

  roundDetails.matches.map((matchString, i) => {
    const matches = matchString.split('|');
    const results = roundDetails.results[i].split('|');
    matches.map((match, j) => {
      const teams = match.split('-');
      const res = {
        homeTeam: teams[0],
        awayTeam: teams[1],
        result: results[j],
      };
      if (!newRoundDetails.matches[j]) {
        newRoundDetails.matches[j] = {};
      }
      newRoundDetails.matches[j][newRoundDetails.leagues[i].id] = res;
    });
  });
  return newRoundDetails;
}

/**
 * Scroll to html element
 *
 * @memberof utils/common
 * @param {string} elementId
 * @returns {void}
 */
export function scrollTo(elementId) {
  const scrollArea = document.getElementsByClassName('main-wrapper')[0];
  const element = document.getElementById(elementId);
  if (scrollArea && element) {
    try {
      scrollArea.scrollTo({
        top: element.getBoundingClientRect().y,
        behavior: 'smooth',
      });
    } catch (error) {
      // eslint-disable-next-line no-console
      console.log(error);
    }
  }
}

/**
 * Getting page name and section in sidebar from route pathname
 *
 * @param {string} pathname
 * @returns {object}
 */
export function parseRoute(pathname) {
  const path = pathname.split('/').pop();
  const selectedMenu = path && path.split('_')[0];
  let heading = '';
  Object.keys(MENU_ITEMS).map((k) => {
    Object.keys(MENU_ITEMS[k]).map((kk) => {
      if (MENU_ITEMS[k][kk].path === pathname) {
        heading = MENU_ITEMS[k][kk].name;
      }
    });
  });

  return { selectedMenu, selectedMenuItem: pathname, heading };
}

export function getChildPathname(pathname) {
  if (!pathname) return '';
  return pathname.split('/')?.pop() || '';
}

/**
 * Getting Filter from URL for setting as default upon page refresh
 *
 * @param {string} url
 * @param {string} filterField
 * @returns {string}
 */
export function setFilterFromUrl(url, filterField) {
  const filterFromUrl = Object.fromEntries(new URLSearchParams(url));
  let filterValue = '';
  if (Object.keys(filterFromUrl).includes(filterField)) {
    filterValue = filterFromUrl[filterField];
  }
  return filterValue;
}

/**
 * replaces empty values in object by 0
 *
 * @param {object} obj
 * @returns {object} updated object
 */
export function convertEmptyInputToZero(obj) {
  const response = { ...obj };
  const keys = Object.keys(obj);
  keys.forEach((key) => {
    if (!response[key]) {
      response[key] = 0;
    }
  });
  return response;
}

/**
 * converts number to percentage
 *
 * @param {number} num
 * @param {number} decimalPlaces
 * @returns {number} formatted number
 */
export function convertToPercentage(num, decimalPlaces = 2) {
  return (parseFloat(num) * 100).toFixed(decimalPlaces);
}

/**
 * converts number back to format used on BE
 *
 * @param {number} num
 * @returns {number} formatted
 */
export function formatPercentageToFitBE(num) {
  return parseFloat(num) / 100 || 0;
}

/**
 * converts BE number format into integer
 *
 * @param {number} num
 * @returns {number} formatted number
 */
export function convertBEFormatToInteger(num) {
  if (typeof num !== 'number') return 0;
  return num / 100;
}

export const convertNigeriaDateTimeToUTC = (dateTimeString) => {
  if (!dateTimeString) return '';

  const NigeriaToUTCDiff = 60 * 60 * 1000;
  const updatedDateTime = new Date(dateTimeString);
  updatedDateTime.setTime(
    updatedDateTime.getTime() + updatedDateTime.getTimezoneOffset() * 60 * 1000 - NigeriaToUTCDiff
  );

  const date = updatedDateTime.getDate()?.toString()?.padStart(2, 0);
  const month = (updatedDateTime.getMonth() + 1)?.toString()?.padStart(2, 0);
  const year = updatedDateTime.getFullYear();
  const hour = updatedDateTime.getHours()?.toString()?.padStart(2, 0);
  const min = updatedDateTime.getMinutes()?.toString()?.padStart(2, 0);
  const seconds = updatedDateTime.getSeconds()?.toString()?.padStart(2, 0);

  return `${year}-${month}-${date}T${hour}:${min}:${seconds}`;
};

/**
 * adjusts date and time according to Nigerian timezone
 * uses "en-GB" option to obtain specific format "29/08/2022, 08:11:00"
 *
 * @param {string} date "2022-01-01"
 * @param {string} time "hh:mm"
 * @returns {object} { date: 2022-01-01, time: hh:mm}
 */
export const convertDateTimeToNigerian = (date, time) => {
  if (!date || !time) return { date: '', time: '' };

  const dateTimeString = `${date}T${time}:00Z`;
  const dateTimeNigeria = new Date(dateTimeString).toLocaleString('en-GB', { timeZone: 'Africa/Lagos' });

  const dateTimeArr = dateTimeNigeria?.split(', ');
  const dateArr = dateTimeArr?.[0]?.split('/');
  const timeArr = dateTimeArr?.[1]?.split(':');
  const finalDate = dateArr.reverse().join('-');

  const finalTime = `${timeArr?.[0]}:${timeArr?.[1]}`;

  return {
    date: finalDate,
    time: finalTime,
  };
};

/**
 * format date string according to format 2021-09-27
 *
 * @param {Date} date
 * @returns {string} 2021-09-27
 */
const formatFullDateString = (date) => {
  if (!date) return '';
  const year = date.getFullYear();
  const month = date.getMonth() + 1;
  const currentDate = date.getDate();

  return `${year}-${month?.toString()?.padStart(2, '0')}-${currentDate?.toString()?.padStart(2, '0')}`;
};

/**
 * get date interval from (currentDate, currentMonth, currentYear - 1)
 * to
 * (currentDate,currentMonth, currentYear + 1)
 *
 * @returns {object} { startDate: 2021-09-27 00:00, endDate: 2023-09-27 23:59}
 */
export const getDateIntervalLastYearToNextYear = () => {
  const lastYearsDate = new Date();
  const nextYearsDate = new Date();

  const currentYear = new Date().getFullYear();
  lastYearsDate.setFullYear(currentYear - 1);
  nextYearsDate.setFullYear(currentYear + 1);

  return {
    startDate: formatFullDateString(lastYearsDate),
    endDate: formatFullDateString(nextYearsDate),
  };
};

/**
 * @param {number} num
 * @param {integer} digit
 * @returns {string}
 */
function padToNDigits(num, digit = 2) {
  return num.toString().padStart(digit, '0');
}

/**
 * format time to hh:mm:ss.sss
 *
 * @function
 * @param {integer} milliseconds
 * @returns {string} string
 */
export function formatTimer(milliseconds) {
  if (milliseconds === null || milliseconds <= 0) {
    return '00:00:00.000';
  }
  let seconds = Math.floor(milliseconds / 1000);
  let minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  seconds = seconds % 60;
  minutes = minutes % 60;
  const milseconds = milliseconds % 1000;

  return `${padToNDigits(hours)}:${padToNDigits(minutes)}:${padToNDigits(seconds)}.${padToNDigits(milseconds, 3)}`;
}