reducers/tickets.js

import { fromJS } from 'immutable';
import {
  reCountPlacedBetsRecord,
} from '../utils/common';
import {
  CLEAR_MY_BETS, SELECT_TICKET,
  LIVE_FINISHED,
  GET_LEAGUE_TABLE_SUCCESS,
  GET_RESULTS_TABLES_SUCCESS,
  SET_BETS_LOADER,
  GET_TICKETS_SUCCESS,
  GET_TICKETS_NO_MORE_BETS,
  SET_NUM_OF_BETS,
  GET_INIT_SUCCESS,
  GET_LEAGUE_TABLE,
  GET_RESULTS_TABLES,
  RESET_RESULTS_DATA,
  CLEAR_NUM_OF_BETS,
  SET_SCROLL_POSITION,
  RE_COUNT_BET,
  SET_BLOCK_MULTIPLE_RE_COUNT,
  SET_PLACED_BETS_RECORD,
  ADD_NEXT_ROUND_BET,
  REMOVE_TICKETS_FROM_COUNT,
  ADD_TICKET_TO_THE_COUNT,
  SCHEDULE_BET_COUNT,
  REMOVE_ALL_TICKETS_FROM_COUNT,
} from '.';
import { GAME_TYPE } from '../constants';

/**
 * @namespace reducer/ticketsReducer
 */
const initialState = fromJS({
  tickets: null,
  lastTimestamp: null,
  lastRunning: 1,
  betsPending: false,
  noMoreBets: false,
  selectedTicket: null,
  scrollTo: 0,
  numberOfBetsLive: 0,
  numberOfBets: 0,
  numberOfBetsNextRound: 0,
  numberOfBetsLiveTurbo: 0,
  numberOfBetsTurbo: 0,
  numbets: 0,
  results: null,
  teams: null,
  ticketDates: null,
  leagueTableWeek: '',
  isResultsLoading: false,
  ticketsUpdated: false,
  placedBetsRecord: null,
  blockMultipleRecount: false,
  clasicTickets: {},
  turboTickets: {},
  betCountSchedule: {},
});

/**
 * @memberof reducer/ticketsReducer
 * @param {object}  state Contain initial and final state of data
 * @param {object}  action Return the action object
 *
 * @property {Array}  [tickets=null]
 * @property {Time}  [lastTimestamp=null]
 * @property {number}  [lastRunning=1]
 * @property {boolean}  [betsPending=false]
 * @property {boolean}  [noMoreBets=false] Set to true when API return empty array.
 *  User has scrolled to the bottom
 * @property {object}  [selectedTicket=null]
 * @property {number}  [scrollTo=0] Use when ucer come back from TICKET_DETAILS
 *  page to TICKETS page. Use to scroll to last previewed ticket.
 * @property {number}  [numberOfBetsLive=0] Number of placed bets for live week
 * @property {number}  [numberOfBets=0]  Number showen into bottom navigation as number of bets
 * @property {number}  [numberOfBetsLiveTurbo=0] Number of placed bets for live week Turbo game
 * @property {number}  [numberOfBetsTurbo=0]  Number showen into bottom navigation
 *  as number of bets Turbo game
 * @property {number}  [numbets=0] Number of bets loaded on API get tickets call
 * @property {Array}  [results=null]
 * @property {Array}  [teams=null]
 * @property {Array}  [ticketDates=null] Array of all dates on bet history page
 * @property {number}  [leagueTableWeek='']
 * @property {number}  [isResultsLoading=true]
 * @property {boolean} [ticketsUpdated] set to true when tickets get updated
 * @returns {state}
 */
function ticketsReducer(state = initialState, action) { // NOSONAR
  let numberOfBetsLive = state.get('numberOfBetsLive');
  let numberOfBets = state.get('numberOfBets');
  let numberOfBetsNextRound = state.get('numberOfBetsNextRound');
  let numberOfBetsLiveTurbo = state.get('numberOfBetsLiveTurbo');
  let numberOfBetsTurbo = state.get('numberOfBetsTurbo');
  const scrollableElementId = 'scroll-area';

  switch (action.type) {
    /**
     * [Received Data]
     * This action is use to set numbets on initial call
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~GET_INIT_SUCCESS
     */
    case GET_INIT_SUCCESS:
      return state
        .set('numbets', action.payload.numbets);
    /**
     * [Action Creator]
     * This action is use to clear tickets for another comming on TICKETS page
     *
     * @memberof reducer/ticketsReducer
     * @example clearMyBets(payload)
     * @function reducer/ticketsReducer~CLEAR_MY_BETS
     */
    case CLEAR_MY_BETS: {
      return state
        .set('ticketDates', null)
        .set('tickets', null)
        .set('lastTimestamp', null)
        .set('lastRunning', 1)
        .set('betsPending', false)
        .set('noMoreBets', false);
    }
    /**
     * [Action Creator]
     * This action is used to set position of the scrollable element
     *
     * @memberof reducer/ticketsReducer
     * @example selectTicket(payload)
     * @function reducer/ticketsReducer~SET_SCROLL_POSITION
     */
    case SET_SCROLL_POSITION: {
      const element = document.getElementById(scrollableElementId);
      return state
        .set('scrollTo', element ? element.scrollTop : 0);
    }
    /**
     * [Action Creator]
     * This action is use to change selected tickets for details
     *
     * @memberof reducer/ticketsReducer
     * @example selectTicket(payload)
     * @function reducer/ticketsReducer~SELECT_TICKET
     */
    case SELECT_TICKET: {
      const element = document.getElementById(scrollableElementId);
      return state
        .set('selectedTicket', fromJS(action.payload.selectedTicket))
        .set('scrollTo', element ? element.scrollTop : 0);
    }
    /**
     * [Action Creator]
     * This action is use to recalculate number of placed bets after live finish
     *
     * @memberof reducer/ticketsReducer
     * @example liveFinished(payload)
     * @function reducer/ticketsReducer~LIVE_FINISHED
     */
    case LIVE_FINISHED: {
      if (action.payload.gameType === GAME_TYPE.TURBO) {
        numberOfBetsTurbo = 0;
        numberOfBetsLiveTurbo = 0;
      } else {
        numberOfBets = numberOfBetsNextRound;
        numberOfBetsNextRound = 0;
        numberOfBetsLive = 0;
      }
      return state
        .set('numberOfBets', numberOfBets)
        .set('numberOfBetsNextRound', numberOfBetsNextRound)
        .set('numberOfBetsLive', numberOfBetsLive)
        .set('numberOfBetsTurbo', numberOfBetsTurbo)
        .set('numberOfBetsLiveTurbo', numberOfBetsLiveTurbo);
    }
    case ADD_NEXT_ROUND_BET:
      numberOfBetsNextRound += 1;
      return state
        .set('numberOfBetsNextRound', numberOfBetsNextRound);

    /**
     * [Action Creator]
     * This action is use to reset results and leagueTable data
     *
     * @memberof reducer/ticketsReducer
     * @example resetResultsData(payload)
     * @function reducer/ticketsReducer~SELECT_TICKET
     */
    case RESET_RESULTS_DATA: {
      return state
        .set('teams', null)
        .set('leagueTableWeek', '')
        .set('results', null);
    }
    /**
     * [Received Data]
     * This action is use to set statistic data
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~GET_LEAGUE_TABLE_SUCCESS
     */
    case GET_LEAGUE_TABLE_SUCCESS:
      return state
        .set('teams', fromJS(action.payload.teams))
        .set('leagueTableWeek', action.payload.leagueTableWeek)
        .set('isResultsLoading', false);

    /**
     * [Received Data]
     * This action is use to set results data
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~GET_RESULTS_TABLES_SUCCESS
     */
    case GET_RESULTS_TABLES_SUCCESS:
      return state
        .set('results', fromJS(action.payload.results))
        .set('isResultsLoading', false);
    /**
     * [Received Data]
     * This action is use to set bet history loader
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~SET_BETS_LOADER
     */
    case SET_BETS_LOADER:
      return state
        .set('betsPending', action.payload.betsPending);
    /**
     * [Received Data]
     * This action is use to set bet history data
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~GET_TICKETS_SUCCESS
     */
    case GET_TICKETS_SUCCESS:
      return state
        .set('tickets', fromJS(action.payload.tickets))
        .set('lastTimestamp', action.payload.lastTimestamp)
        .set('lastRunning', action.payload.lastRunning)
        .set('ticketDates', fromJS(action.payload.ticketDates))
        .set('betsPending', false)
        .set('selectedTicket', fromJS(action.payload.selectedTicket))
        .set('ticketsUpdated', action.payload.ticketsUpdated);
    /**
     * [Received Data]
     * This action is use to stop call getTicket because user got all tickets
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~GET_TICKETS_NO_MORE_BETS
     */
    case GET_TICKETS_NO_MORE_BETS:
      return state
        .set('noMoreBets', true)
        .set('betsPending', false);
    /**
     * [Received Data]
     * This action is use to set number of placed bets
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~SET_NUM_OF_BETS
     */
    case SET_NUM_OF_BETS: {
      return state
        .set('numberOfBets', action.payload.numberOfBets ? action.payload.numberOfBets : numberOfBets)
        .set('numberOfBetsLive', action.payload.numberOfBetsLive ? action.payload.numberOfBetsLive : numberOfBetsLive)
        .set('numberOfBetsTurbo', action.payload.numberOfBetsTurbo ? action.payload.numberOfBetsTurbo : numberOfBetsTurbo)
        .set('numberOfBetsLiveTurbo', action.payload.numberOfBetsLiveTurbo ? action.payload.numberOfBetsLiveTurbo : numberOfBetsLiveTurbo);
    }
    /**
     * [Received Data]
     * This action is use to set loader on results and leagues page
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~GET_LEAGUE_TABLE~GET_RESULTS_TABLES
     */
    case GET_LEAGUE_TABLE:
    case GET_RESULTS_TABLES:
      return state
        .set('isResultsLoading', true);
    /**
     * [Received Data]
     * This action is use to clear number of bets
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~CLEAR_NUM_OF_BETS
     */
    case CLEAR_NUM_OF_BETS:
      return state
        .set('numberOfBets', action.payload.numberOfBets);
    case SET_PLACED_BETS_RECORD:
      return state
        .set('numberOfBets', action.payload.numberOfBets ? action.payload.numberOfBets : numberOfBets)
        .set('placedBetsRecord', fromJS(action.payload.placedBetsRecord));

    /**
     * [Received Data]
     * This action is use to update the bet counter
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~RE_COUNT_BET
     */
    case RE_COUNT_BET: {
      // eslint-disable-next-line no-shadow
      const { placedBetsRecord, numberOfBets } = reCountPlacedBetsRecord({
        arr: action.payload.placedBetsRecord,
        pastWeek: action.payload.pastWeek || 0,
        currentWeek: action.payload.currentWeek || 0,
        gameType: action.payload.gameType,
      });
      return state
        .set('numberOfBets', numberOfBets)
        .set('placedBetsRecord', fromJS(placedBetsRecord))
        .set('blockMultipleRecount', false);
    }
    /**
     * [Received Data]
     * This action is use to block multiple recount on multiple bet action
     *
     * @memberof reducer/ticketsReducer
     * @function reducer/ticketsReducer~SET_BLOCK_MULTIPLE_RE_COUNT
     */
    case SET_BLOCK_MULTIPLE_RE_COUNT:
      return state
        .set('blockMultipleRecount', action.payload);
    case ADD_TICKET_TO_THE_COUNT: {
      const round = action.payload.roundId;
      const gameType = action.payload.gameType;
      const count = action.payload.count;
      const ticketsCount = gameType === GAME_TYPE.TURBO ? state.get('turboTickets').toJS() : state.get('clasicTickets').toJS();

      if (ticketsCount[round] === undefined) {
        ticketsCount[round] = count;
      } else {
        ticketsCount[round] += count;
      }

      const clasicTickets = gameType === GAME_TYPE.TURBO ? state.get('clasicTickets') : fromJS(ticketsCount);
      const turboTickets = gameType === GAME_TYPE.TURBO ? fromJS(ticketsCount) : state.get('turboTickets');

      return state
        .set('turboTickets', turboTickets)
        .set('clasicTickets', clasicTickets);
    }
    case REMOVE_TICKETS_FROM_COUNT: {
      const schedule = state.get('betCountSchedule').toJS();

      const round = action.payload.roundId;
      const gameType = action.payload.gameType;
      const ticketsCount = gameType === GAME_TYPE.TURBO ? state.get('turboTickets').toJS() : state.get('clasicTickets').toJS();

      const roundIds = Object.keys(ticketsCount);
      for (let i = 0; i < roundIds.length; i += 1) {
        const roundId = roundIds[i];
        if (roundId <= round) {
          delete ticketsCount[roundId];
          delete schedule[roundId];
        }
      }

      const clasicTickets = gameType === GAME_TYPE.TURBO ? state.get('clasicTickets') : fromJS(ticketsCount);
      const turboTickets = gameType === GAME_TYPE.TURBO ? fromJS(ticketsCount) : state.get('turboTickets');

      return state
        .set('turboTickets', turboTickets)
        .set('clasicTickets', clasicTickets)
        .set('betCountSchedule', fromJS(schedule));
    }
    case REMOVE_ALL_TICKETS_FROM_COUNT: {
      return state
        .set('turboTickets', fromJS({}))
        .set('clasicTickets', fromJS({}))
        .set('betCountSchedule', fromJS({}));
    }
    case SCHEDULE_BET_COUNT: {
      const round = action.payload.roundId;
      const gameType = action.payload.gameType;
      const time = action.payload.time;

      const schedule = state.get('betCountSchedule').toJS();
      schedule[round] = { gameType, time };

      return state.set('betCountSchedule', fromJS(schedule));
    }
    default:
      return state;
  }
}
export default ticketsReducer;