utils/common.js

/* eslint-disable no-param-reassign */
/**
 * @namespace utils/common
 */
import Constants from '../constants';

/**
 * Remove scroll listener from scroll area
 *
 * @memberof utils/common
 * @returns {void}
 */
export function removeListener() {
  const scrollArea = document.getElementsByClassName('scroll-area')[0];
  if (scrollArea) {
    scrollArea.classList.remove('listener');
    scrollArea.scrollTo(0, 0);
  }
}

/**
 * Check if it is some of TICKET pages
 *
 * @memberof utils/common
 * @function
 * @param {string} targetPage
 * @returns {boolean}
 */
export const isTicketPage = (targetPage) => Constants.PAGES.TICKETS === targetPage
  || Constants.PAGES.TICKET_DETAILS === targetPage;

/**
 * Check if it is some of LIVE pages
 *
 * @memberof utils/common
 * @function
 * @param {string} currentPage
 * @returns {boolean}
 */
export const isLivePage = (currentPage) => Constants.PAGES.LIVE === currentPage
  || Constants.PAGES.ALL_LIVE === currentPage || Constants.PAGES.MY_LIVE === currentPage;

/**
 * Check if it is not some of RESULT or TICKET pages
 *
 * @memberof utils/common
 * @function
 * @param {string} targetPage
 * @returns {boolean}
 */
export const openLiveStartedModal = (targetPage) => (
  Constants.PAGES.RESULTS !== targetPage && Constants.PAGES.LEAGUE_TABLE !== targetPage
  && !isTicketPage(targetPage) && Constants.PAGES.LOGIN !== targetPage
);

/**
 * Find selection in passed market by selection id
 *
 * @memberof utils/common
 * @param {object} market
 * @param {number} index
 * @returns {string}
 */
export function getSelection(market, index) {
  if (market.submarkets) {
    const sub = market.submarkets.find((subselection) => subselection.selections[index]);
    if (sub) {
      return sub.selections[index];
    }
  } else if (market.selections[index]) {
    return market.selections[index];
  }
  return null;
}

/**
 * Find selection in passed market by selection id
 *
 * @memberof utils/common
 * @param {object} placedSelections
 * @param {number} leagueId
 * @param {number} matchId
 * @returns {string}
 */
export function getSelectionNames(placedSelections, leagueId, matchId) {
  if (!placedSelections) {
    return '';
  }
  const leagueSelections = placedSelections[leagueId] || {};
  const matchSelections = leagueSelections[matchId] || [];
  const names = matchSelections.map((selection) => selection.selection.name);
  return names.join(', ');
}

/**
 * Extract WinningScores
 *
 * @memberof utils/common
 * @param {object} market
 * @param {number} selectionId
 * @returns {string}
 */
export function extractWinningScores(market, selectionId) {
  if (market.submarkets) {
    const properMarket = market
      .submarkets.filter((x) => Object.keys(x.selections).indexOf(selectionId) !== -1)[0];
    return properMarket.selections[selectionId].winningScores;
  }
  return market.selections[selectionId].winningScores;
}

/**
 * Find selection in all markets by selection id
 *
 * @memberof utils/common
 * @param {number} selectionIndex
 * @param {Array} markets
 * @returns {string}
 */
export function getSelectionName(selectionIndex, markets) {
  let selection = null;
  for (let i = 0; i < markets.length; i += 1) {
    selection = getSelection(markets[i], selectionIndex);
    if (selection) {
      return selection;
    }
  }
  return '';
}

/**
 * Changing color of placed bet depend on winning or losing bet
 *
 * @memberof utils/common
 * @param {object} placedSelections
 * @param {number} leagueIndex
 * @param {number} matchId
 * @param {string} score
 * @returns {object}
 */
export const calulatePlacedSelection = (placedSelections, leagueIndex, matchId, score) => {
  const pSelections = placedSelections;
  if (pSelections[leagueIndex] && pSelections[leagueIndex][matchId]) {
    pSelections[leagueIndex][matchId].map((placed) => {
      // if (placed.selection.alwaysWin && placed.colorId === 2) {
      //   console.log('ALWAYS WIN, IGNORE', placed.selection.name, score);
      // } else if (placed.selection.alwaysLose && placed.colorId === -1) {
      //   console.log('ALWAYS LOSE, IGNORE', placed.selection.name, score);
      // } else
      if (placed.selection.winningScores.indexOf(score) !== -1) {
        // console.log('COLOR - WIN', placed.selection.name, score, placed.colorId);
        placed.colorId = placed.selection.alwaysWin
          ? Constants.COLOR_IDS.ALWAYS_WIN : Constants.COLOR_IDS.WIN;
      } else if (placed.selection.alwaysLose) {
        // console.log('SET ALWAYS LOSE', placed.selection.name, score);
        placed.colorId = Constants.COLOR_IDS.ALWAYS_LOSE;
      } else {
        // console.log('COLOR - LOSE', placed.selection.name, score, placed.colorId);
        placed.colorId = Constants.COLOR_IDS.LOSE;
      }
    });
  }
  return pSelections;
};

/**
 * Create colne of object with different reference
 *
 * @memberof utils/common
 * @param {object} obj
 * @returns {object}
 */
export function newObjectRef(obj) {
  let copy = {};
  copy = Object.assign(copy, obj);
  return copy;
}

/**
 * Compare 2 numbers.
 * Return 1 if first is bigger then second.
 * Retun 0 if numbers are equal.
 * Return -1 if second is bigger then first.
 *
 * @memberof utils/common
 * @function
 * @param {number} x
 * @param {number} y
 * @returns {number}
 */
const compare = (x, y) => (x > y ? 1 : x === y ? 0 : -1);

/**
 * Compare home scores
 *
 * @memberof utils/common
 * @param {number} a
 * @param {number} b
 * @returns {number}
 */
export function sortByHomeScores(a, b) {
  const x = a.scoreHome;
  const y = b.scoreHome;
  return compare(x, y);
}

/**
 * Compare away scores
 *
 * @memberof utils/common
 * @param {number} a
 * @param {number} b
 * @returns {number}
 */
export function sortByAwayScores(a, b) {
  const x = a.scoreAway;
  const y = b.scoreAway;
  return compare(x, y);
}

/**
 * Compare home scores then away scores
 *
 * @memberof utils/common
 * @param {number} a
 * @param {number} b
 * @returns {number}
 */
export function sortByHomeThenAwayScores(a, b) {
  const firstSort = sortByHomeScores(a, b);
  return (firstSort === 1 || (firstSort === 0 && sortByAwayScores(a, b) ? 1 : -1)
  );
}

/**
 * Compare away scores then home scores
 *
 * @memberof utils/common
 * @param {number} a
 * @param {number} b
 * @returns {number}
 */
export function sortByAwayThenHomeScores(a, b) {
  const firstSort = sortByAwayScores(a, b);
  return (firstSort === 1 || (firstSort === 0 && sortByHomeScores(a, b) ? 1 : -1)
  );
}

/**
 * Calculate game timers for betting round and live round
 *
 * @memberof utils/common
 * @param {Time} roundEnd
 * @param {Time} live
 * @param {number} liveMatchDuration
 * @param {number} noBettingTimeCountdown
 * @returns {object} Return seconds to end betting round and seconds to end live game
 */
export function setupCounter(roundEnd, live, liveMatchDuration, noBettingTimeCountdown) {
  const now = new Date().getTime();
  let countdown = null;
  const diffSec = parseInt((roundEnd.getTime() - now) / 1000);
  if (live) {
    const diffLive = Math.ceil((live.getTime() - now) / 1000);
    countdown = parseInt(diffLive + liveMatchDuration);
    if (diffLive > 0 && diffLive <= noBettingTimeCountdown) {
      return { diffSec: diffLive, countdown, isLive: true };
    }
  }
  return { diffSec, countdown };
}

/**
 * Parse time
 *
 * @memberof utils/common
 * @param {Time} diffSec
 * @returns {string} Return parsed minutes and seconds MM:SS
 */
export function getTimeFormat(diffSec) {
  let minLeft = parseInt(diffSec / 60);
  let secLeft = parseInt(diffSec - (minLeft * 60));
  minLeft = minLeft < 10 ? `0${minLeft}` : minLeft;
  secLeft = secLeft < 10 ? `0${secLeft}` : secLeft;
  return diffSec < 0 ? '00:00' : `${minLeft}:${secLeft}`;
}

/**
 * Return bet type based on typeID
 *
 * @memberof utils/common
 * @param {object} ticket
 * @returns {string}
 */
export function handleType(ticket) {
  const type = parseInt(ticket.type);
  switch (type) {
    case Constants.BET_TYPE_VALUES.SINGLE:
      return Constants.BET_TYPE.SINGLE;
    case Constants.BET_TYPE_VALUES.COMBINATION:
      return Constants.BET_TYPE.COMBINATION;
    case Constants.BET_TYPE_VALUES.SPLIT_COLUMN:
      return Constants.BET_TYPE.SPLIT_COLUMN;
    default:
      return parseInt(ticket.numberOfBets) > 3
        ? `${Constants.DIGITS[(ticket.numberOfBets - 1)] || ticket.numberOfBets} Fold`
        : Constants.DIGITS[ticket.numberOfBets - 1];
  }
}

/**
 * Check if typeID is some of combination bet types
 *
 * @memberof utils/common
 * @function
 * @param {number} type
 * @returns {boolean}
 */
export const isCombi = (type) => (
  parseInt(type) === Constants.BET_TYPE_VALUES.COMBINATION
  || parseInt(type) === Constants.BET_TYPE_VALUES.SPLIT_COLUMN
);

/**
 *  Check if typeID is single with multiple bet
 *
 * @memberof utils/common
 * @function
 * @param {number} ticket
 * @returns {boolean}
 */
export const isSingleMultipleBet = (ticket) => (
  parseInt(ticket.type) === Constants.BET_TYPE_VALUES.SINGLE
  && ticket.bets.length > 1
);

/**
 * Parse minimum and maximum odds for passed bet type
 *
 * @memberof utils/common
 * @function
 * @param {object} ticket
 * @returns {string}
 */
export const getTicketOdds = (ticket) => (
  ticket.maxOdd && ticket.minOdd !== ticket.maxOdd
    ? `${ticket.minOdd} - ${ticket.maxOdd}`
    : ticket.minOdd
);

/**
 * Calculate total stake, potential win (max and min) and bonus amount
 *
 * @memberof utils/common
 * @param {object} calc Previous calculation
 * @param {number} stake
 * @param {number} bonusOddMax
 * @param {number} bonusOddMin
 * @param {number|null} numOfBets
 * @param {object} manager
 * @returns {object}
 */
export function setupCalc(calc, stake, bonusOddMax, bonusOddMin, numOfBets, manager) {
  const calculation = calc;
  const value = parseInt(stake);
  if (stake && value) {
    calculation.totalStake = parseInt(calculation.totalStake)
      + (value * (numOfBets || manager?.NUM || 1));
    calculation.potWinMax = parseFloat(calculation.potWinMax) + (value * bonusOddMax);
    const tempPotMinWin = value * bonusOddMin;
    calculation.potWinMin = calculation.potWinMin === 0 || calculation.potWinMin > tempPotMinWin
      ? tempPotMinWin : calculation.potWinMin;
    if (manager) { calculation.bonusAmt += value * manager.BONUSMAX; }
  }

  return calculation;
}

/**
 * Calculate angle of loader for no bet coundown
 *
 * @memberof utils/common
 * @param {object} style
 * @returns {object}
 */
export function computeLoader(style) {
  const s = style;
  if (s.angle1 + s.increment >= 270 && s.secondHalf === false) {
    s.angle2 = 180;
    if (s.angle1 + s.increment > 270) {
      s.angle2 -= 270 - s.angle1;
    }
    s.angle1 = 90;
    s.secondHalf = true;

    const temp = s.progress__bg;
    s.progress__bg = s.progress__slice;
    s.progress__slice = temp;
  }
  if (s.secondHalf === true) {
    s.angle2 += s.increment;
  } else {
    s.angle1 += s.increment;
  }
  return s;
}

/**
 * Provide setTimeout delay
 *
 * @memberof utils/common
 * @function
 * @param {number} time  Delay time
 * @returns {Promise}
 */
export const delay = (time) => new Promise((resolve) => setTimeout(resolve, time));

/**
 * Calculate :
 * oldData [ when round end is in the past ],
 * haveLiveMatches [ when live is started and still not ended ],
 * isNoBetTime [ live is started in less then noBettingTimeCountdown seconds ],
 * leftTime [ left seconds till live start ]
 *
 * @memberof utils/common
 * @param {Time} endDate
 * @param {Time} liveStartDate
 * @param {number} liveMatchDuration
 * @param {number} noBettingTimeCountdown
 * @returns {object}
 */
export function roundSetupTimers(
  endDate,
  liveStartDate,
  liveMatchDuration,
  noBettingTimeCountdown,
) {
  const roundEnd = new Date(endDate);
  const liveStart = new Date(liveStartDate);
  const now = new Date().getTime();

  // recived the same roundId that we have as current round
  const oldData = roundEnd.getTime() - now - (noBettingTimeCountdown * 1000) < 0;

  const leftTime = parseInt((liveStart.getTime() - now) / 1000);
  const isNoBetTime = leftTime >= 0 && leftTime <= noBettingTimeCountdown;

  // user enter the site when is no betting time

  let haveLiveMatches = false;

  // after no bet time setup new round
  if (!isNoBetTime) {
    haveLiveMatches = now > liveStart.getTime()
      && now <= liveStart.getTime() + (liveMatchDuration * 1000);
  }
  return {
    oldData, haveLiveMatches, isNoBetTime, liveStart, roundEnd, leftTime,
  };
}
/**
 * Sort free bets by expiration date
 *
 * @memberof utils/common
 * @param {Array} freeBets
 * @returns {Array}
 */
export function sortFreeBets(freeBets) {
  freeBets = freeBets.sort((a, b) => (
    new Date(a.expirationDate) < new Date(b.expirationDate) ? -1 : 1));
  return freeBets;
}

/**
 * Parse time
 *
 * @memberof utils/common
 * @param {Time} diffSec
 * @returns {string} Return template minutes and seconds
 */
export function getTimeTextFormat(diffSec) {
  const minLeft = parseInt(diffSec / 60);
  const secLeft = parseInt(diffSec - (minLeft * 60));
  const minText = minLeft < 2 ? 'minute' : 'minutes';
  return diffSec < 0 ? '00:00'
    : minLeft < 1
      ? `${secLeft} seconds`
      : secLeft < 1
        ? `${minLeft} ${minText}`
        : `${minLeft} ${minText} and ${secLeft} seconds`;
}

/**
 * addToPlacedBetsRecord
 *
 * @memberof utils/common
 * @param {Array} placedBetRecordsArr
 * @param {object} recordsParams
 * @returns {Array} Return array with new placed bet records
 */
export function addToPlacedBetsRecord(placedBetRecordsArr, recordsParams) {
  const curentRecordIndex = placedBetRecordsArr.findIndex(
    (obj) => (
      obj.currentWeek === recordsParams.currentWeek
      && obj.gameType === recordsParams.gameType
    ),
  );
  if (curentRecordIndex > -1) {
    placedBetRecordsArr[curentRecordIndex].counter += 1;
  } else {
    placedBetRecordsArr.push({
      gameType: recordsParams.gameType,
      pastWeek: recordsParams.pastWeek,
      currentWeek: recordsParams.currentWeek,
      counter: 1,
    });
  }
  return placedBetRecordsArr;
}

/**
 * updateBetCounter
 *
 * @memberof utils/common
 * @param {Array} placedBetRecordsArr
 * @returns {number} Return updated counter
 */
export function updateBetCounter(placedBetRecordsArr) {
  let counter = 0;
  if (placedBetRecordsArr.length > 0) {
    placedBetRecordsArr.map((item) => { counter += item.counter; });
  }
  return counter;
}

/**
 * parseCouponData
 *
 * @memberof utils/common
 * @param {number} betType
 * @param {string} selections
 * @param {string} stake
 * @returns {object} Coupon data
 */
export function parseCouponData(betType, selections, stake) {
  const result = { selections: selections.split('$').map((x) => `${x}:1.00`) };
  switch (betType) {
    case Constants.BET_TYPE_VALUES.SINGLE:
      result.group = 1;
      break;
    case Constants.BET_TYPE_VALUES.MULTIPLE:
      result.group = selections.split('$').length;
      break;
    case Constants.BET_TYPE_VALUES.COMBINATION:
      result.group = Math.min(...stake.split('&').slice(0, -1).map((x) => parseInt(x.split(':')[0])));
      break;
    case Constants.BET_TYPE_VALUES.SPLIT_COLUMN:
      result.group = parseInt(stake.split(':')[0]);
      break;
    default:
      break;
  }
  return result;
}

/**
 * remapMarketsToSelectionWinningScores
 *
 * @memberof utils/common
 * @param {Array} markets
 * @returns {object} Map (selection, WinningScores)
 */
export function remapMarketsToSelectionWinningScores(markets) {
  const result = {};

  for (let i = 0; i < markets.length; i += 1) {
    const market = markets[i];

    if (market.submarkets === undefined) {
      const selectionIds = Object.keys(market.selections);
      for (let j = 0; j < selectionIds.length; j += 1) {
        const selectionId = selectionIds[j];
        result[selectionId] = market.selections[selectionId].winningScores;
      }
    } else {
      for (let j = 0; j < market.submarkets.length; j += 1) {
        const submarket = market.submarkets[j];
        const selectionIds = Object.keys(submarket.selections);
        for (let k = 0; k < selectionIds.length; k += 1) {
          const selectionId = selectionIds[k];
          result[selectionId] = submarket.selections[selectionId].winningScores;
        }
      }
    }
  }

  return result;
}

/**
 * reCountPlacedBetsRecord
 *
 * @memberof utils/common
 * @param {object} placedBetRecords
 * @returns {number} Return updated placed bet records and updated counter
 */
export function reCountPlacedBetsRecord(placedBetRecords) {
  const lastRecordIndex = placedBetRecords.arr.findIndex(
    (obj) => (
      obj.currentWeek === parseInt(placedBetRecords.pastWeek)
      && obj.gameType === placedBetRecords.gameType),
  );
  if (lastRecordIndex !== -1) {
    placedBetRecords.arr.splice(lastRecordIndex, 1);
  } else {
    placedBetRecords.arr.shift();
  }
  const counter = updateBetCounter(placedBetRecords.arr);
  return ({
    placedBetsRecord: placedBetRecords.arr,
    numberOfBets: counter,
  });
}

/**
 * reduce selected odds that have same matchId and same league
 *
 * @memberof utils/common
 * @param {Array} selectedOdds
 * @returns {Array}
 */
export function filterDuplicateSelections(selectedOdds) {
  return selectedOdds.filter(
    (selection, index, self) => self.findIndex(
      (sl) => (selection.matchId === sl.matchId && selection.league === sl.league),
    ) === index,
  );
}

/**
 * transform api standings object to map per team
 *
 * @memberof utils/common
 * @param {string} standings
 * @returns {object}
 */
export function transformStandingsPerTeam(standings) {
  const result = {};
  // standings = "LIV-9-WWWxx|MCI-9-WWWxx|ARS-7-WDWxx...."
  const teamsInfo = standings.split('|');
  for (let i = 0; i < teamsInfo.length; i += 1) {
    const teamInfo = teamsInfo[i].split('-');
    result[teamInfo[0]] = { position: i + 1, points: teamInfo[1], last5: teamInfo[2] };
  }
  return result;
}

/**
 * transform api statistics object to map per team
 *
 * @memberof utils/common
 * @param {Array} weeksStatistics
 * @returns {object}
 */
export function transformStatisticsPerTeamLast5(weeksStatistics) {
  const result = {};

  for (let i = 0; i < weeksStatistics.length; i += 1) {
    const weekStatistics = weeksStatistics[i].matches[0];
    if (!weekStatistics) break;
    // weekStatistics.matches => "MUN-NEW|CRY-TOT|CHE-BRH....
    const matches = weekStatistics.matches.split('|');
    // weekStatistics.results = 5:1|2:1|0:0|1:2|3:2|2:2... or 5:1&2:1&0:0&1:2&3:2&2:2...
    const scoresSplitter = weekStatistics.results.indexOf('|') !== -1 ? '|' : '&';
    const scores = weekStatistics.results.split(scoresSplitter);
    for (let j = 0; j < matches.length; j += 1) {
      const match = matches[j];
      const [homeTeam, awayTeam] = match.split('-');
      const [hGoals, aGoals] = scores[j].split(':');

      let hTeamLetter;
      let aTeamLetter;

      if (hGoals > aGoals) {
        hTeamLetter = 'W';
        aTeamLetter = 'L';
      } else if (aGoals > hGoals) {
        hTeamLetter = 'L';
        aTeamLetter = 'W';
      } else {
        hTeamLetter = 'D';
        aTeamLetter = 'D';
      }

      if (!result[homeTeam]) {
        result[homeTeam] = { matches: [] };
      }
      if (!result[awayTeam]) {
        result[awayTeam] = { matches: [] };
      }

      result[homeTeam].matches.push({
        home: homeTeam,
        away: awayTeam,
        score: `${hGoals}-${aGoals}`,
        status: hTeamLetter,
      });
      result[awayTeam].matches.push({
        home: homeTeam,
        away: awayTeam,
        score: `${hGoals}-${aGoals}`,
        status: aTeamLetter,
      });
    }
  }
  return result;
}

/**
 * Convert amount into cents
 *
 * @memberof utils/common
 * @param {number} amount
 * @returns {boolean}
 */
export function convertIntoCents(amount) {
  if (typeof amount !== 'number') {
    return null;
  }
  return amount * 100;
}

/**
 * Convert amount from cents to units (Naira)
 *
 * @memberof utils/common
 * @param {number} amount
 * @returns {boolean}
 */
export function convertIntoUnits(amount) {
  if (typeof amount !== 'number') {
    return null;
  }
  return amount / 100;
}

/**
 * Get default stakes array
 *
 * @memberof utils/common
 * @param {Array} selectedOdds
 * @returns {Array}
 */
export function setDefaultStakesArr(selectedOdds) {
  if (!selectedOdds) {
    return [];
  }
  return new Array(selectedOdds.length).fill('');
}

/**
 * Get filtered selected odds by roundId
 *
 * @memberof utils/common
 * @param {Array} selectedOdds
 * @param {number} roundId
 * @returns {Array}
 */
export function filterSelectedOdds(selectedOdds, roundId) {
  if (!selectedOdds || !roundId) {
    return [];
  }
  return selectedOdds.filter((selectedOdd) => selectedOdd.roundId === roundId);
}