/* eslint-disable no-param-reassign */
import {
takeEvery, put, call, select,
} from 'redux-saga/effects';
/**
* @namespace sagas/init
*/
import Constants, { CNT_PATH, GAME_TYPE } from '../constants';
import { requestGet } from '../utils/request';
import {
parseMarkets,
getPlacedBetsResults,
parseSelectedMarket,
} from '../utils/parser';
import {
GET_INIT_SUCCESS,
CHECK_SESSION,
GET_ROUND_SELECTIONS,
GET_ROUND_SELECTIONS_SUCCESS,
GET_TURBO_ROUND_SELECTIONS,
GET_INIT,
SHOW_ERROR_MODAL,
SET_LOADER,
SELECT_LEAGUE,
GET_ROUND,
GET_TURBO_ROUND,
SELECT_LEAGUE_SUCCESS,
GO_TO_LOGIN,
GET_OPEN_BETS,
TOGGLE_ODDS,
SCHEDULE_BET_COUNT,
ADD_TICKET_TO_THE_COUNT,
SET_LAST_TURBO_ROUND_PLAYED,
ADD_PLACED_BET_BULK,
} from '../reducers';
import {
getMarkets,
getGameType,
} from '../store/bets';
import { getUser } from '../store/common';
import { getSelectedOdds } from '../store/placebet';
/**
* @memberof sagas/init
* @typedef Market
* @type {object}
* @property {string} info - Information about market
* @property {string} name - Market name
* @property {Array<Subselection>} [submarkets] - Present if market have subselection
* @property {Array<Selection>} [selections] - Present if market dont have subselection
*/
/**
* @memberof sagas/init
* @typedef Subselection
* @type {object}
* @property {string} name - Name of subselection
* @property {Array<Selection>} selections - Present if market dont have subselection
*/
/**
* @memberof sagas/init
* @typedef Selection
* @type {object}
* @property {string} name - Name of selection
* @property {string} fullName - Name showen in betslip and tickets details selection
* @property {string} winningScores - Parsed scores. Contain only scores when selection is winning.
* @property {boolean} alwaysWin - Indicate if selection is once win is it surely winning.
* @property {boolean} alwaysLose - Indicate if selection is once lost is it surely losing.
*/
/**
* @memberof sagas/init
* @typedef BetslipSettings
* @type {object}
* @property {Array<number>} accountOptions - Contain showen stake buttons
* @property {number} maxLineBetslip - Maximim number of selections
* @property {number} maxStake - Maximum stake for placebet
* @property {number} maxSystemCombinations - Maximum number of system combinations
* @property {number} minStake - Minimum stake for placebet
* @property {number} minStakePerSelection - Minimum stake for placebet
* for combination and split bet type
*/
/**
* @memberof sagas/init
* @typedef League
* @type {object}
* @property {number} enabled - Is league in use (0-not in use, 1-in use)
* @property {string} flag - Name of flag for league icon
* @property {number} id - League id
* @property {string|null} logo - Not in use
* @property {string} name - League name
*/
/**
* @memberof sagas/init
* @typedef "init/response.data"
* @type {object}
* @property {number} noBettingTime - Duration of No Betting time in seconds
* @property {number} noBettingTimeCountdown - Duration of No Betting time showing modal in seconds
* @property {number} liveMatchDuration - Duration of live match in seconds
* @property {Array<Market>} markets - Define all markets/selections with name and informations
* @property {BetslipSettings} betslipSettings - Configuration of betslip
* @property {object} bonusLeveling - Indicates whether the Courage component is present.
* @property {string} cnt - Config of bonus informations.
* @property {object} destinations - paths of images and links.
* @property {Array<League>} leagues - Leagues definition.
* @property {object} configs - Contain currency symbol.
* @property {number} numbets - Number of showing bets in Bet History.
*/
/**
* Initialize data in app
*
* @memberof sagas/init
* @async
* @yields {put} SET_LOADER
* @yields {call} /game/init
* @yields {put} GET_INIT_SUCCESS
* @yields {put} CHECK_SESSION
* @yields {put} SHOW_ERROR_MODAL
*/
function* init() {
let response;
try {
yield put({
type: SET_LOADER,
payload: {
isLoading: true,
},
});
response = yield call(requestGet, Constants.API_URLS.INIT);
if (response.status === -1) {
throw new Error(response.error.message);
} else {
const newState = response.data;
newState.markets = parseMarkets(newState.markets, newState.correctScoreIndex);
newState.leagues = newState.leagues.map((l) => { l.liveEnabled = l.enabled; return l; });
newState.selectedLeagueIndex = newState.leagues.findIndex((l) => l.enabled === 1);
newState.selectedLeague = newState.leagues[newState.selectedLeagueIndex];
newState.cnt = CNT_PATH || newState.cnt;
// hardcoded market order markets
const marketIdOrder = [
Constants.MARKET_IDS.MARKET_1X2,
Constants.MARKET_IDS.MARKET_OVER_UNDER,
Constants.MARKET_IDS.MARKET_HOME_OVER_UNDER,
Constants.MARKET_IDS.MARKET_AWAY_OVER_UNDER,
Constants.MARKET_IDS.MARKET_CORRECT_SCORE,
Constants.MARKET_IDS.MARKET_GOAL_NO_GOAL,
Constants.MARKET_IDS.MARKET_DOUBLE_CHANCE,
Constants.MARKET_IDS.MARKET_1X2_OVER_UNDER,
Constants.MARKET_IDS.MARKET_MULTIGOAL,
Constants.MARKET_IDS.MARKET_MULTIGOAL_HOME,
Constants.MARKET_IDS.MARKET_MULTIGOAL_AWAY,
Constants.MARKET_IDS.MARKET_DC_OVER_UNDER,
];
const marketMap = {};
for (let i = 0; i < newState.markets.length; i += 1) {
const market = newState.markets[i];
marketMap[market.id] = market;
// sort submarkets for 1X2 + Over/Under
if (market.id === Constants.MARKET_IDS.MARKET_1X2_OVER_UNDER) {
const mId = market.id;
marketMap[mId].submarkets = marketMap[mId].submarkets.sort((a, b) => a.id - b.id);
}
}
const reorderedMarkets = [];
for (let i = 0; i < marketIdOrder.length; i += 1) {
const marketId = marketIdOrder[i];
if (marketMap[marketId]) {
reorderedMarkets.push(marketMap[marketId]);
}
}
newState.markets = reorderedMarkets;
newState.selectedMarket = parseSelectedMarket(newState.markets[0]);
yield put({
type: GET_INIT_SUCCESS,
payload: newState,
});
yield put({
type: CHECK_SESSION,
});
}
} catch (error) {
yield put({
type: SHOW_ERROR_MODAL,
payload: {
activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
message: error.message,
},
});
}
}
/**
* @memberof sagas/init
* @typedef "roundSelections/response.data"
* @type {object}
* @property {Array} selections - Defned by league:match:selection:odd
* (example:["2:3:101:1.37", "2:4:101:1.65"])
* @property {number} numbets - Number of placed bets
*/
/**
* Used for setting placed selections for passed roundId
*
* @memberof sagas/init
* @async
* @param {object} action
* @property {object} action
* @property {object} action.payload
* @property {number} action.payload.roundId - Can be current round for placeing
* bets and current Live round
*
* @yields {call} /bet/roundselections/{roundId}
* @yields {select} getMarkets
* @yields {put} GET_ROUND_SELECTIONS_SUCCESS
* @yields {put} SHOW_ERROR_MODAL
*/
function* roundSelections(action) {
let response;
try {
if (action.payload.roundId) {
response = yield call(requestGet, `${Constants.API_URLS.ROUND_SELECTIONS}/${action.payload.roundId}`, true);
if (response.status !== -1) {
const markets = yield select(getMarkets);
const palcedBets = getPlacedBetsResults(response.data.selections, markets);
yield put({
type: GET_ROUND_SELECTIONS_SUCCESS,
payload: {
placedSelections: palcedBets,
roundId: action.payload.roundId,
},
});
}
}
} catch (error) {
yield put({
type: SHOW_ERROR_MODAL,
payload: {
activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
message: error.message,
},
});
}
}
/**
* Used for setting placed selections for passed roundId
*
* @memberof sagas/init
* @async
* @param {object} action
* @property {object} action
* @property {object} action.payload
* @property {number} action.payload.roundId - Can be current round for placeing
* bets and current Live round
*
* @yields {call} /bet/roundselections/{roundId}
* @yields {select} getMarkets
* @yields {put} GET_ROUND_SELECTIONS_SUCCESS
* @yields {put} SHOW_ERROR_MODAL
*/
function* turboRoundSelections(action) {
let response;
try {
if (action.payload.roundId) {
response = yield call(requestGet, `${Constants.API_URLS.TURBO_ROUND_SELECTIONS}/${action.payload.roundId}`, true);
if (response.status !== -1) {
const markets = yield select(getMarkets);
const palcedBets = getPlacedBetsResults(response.data.selections, markets);
if (response.data.selections.length > 0) {
yield put({
type: SET_LAST_TURBO_ROUND_PLAYED,
payload: { roundId: action.payload.roundId },
});
}
yield put({
type: GET_ROUND_SELECTIONS_SUCCESS,
payload: {
placedSelectionsTurbo: palcedBets,
roundId: action.payload.roundId,
},
});
}
}
} catch (error) {
yield put({
type: SHOW_ERROR_MODAL,
payload: {
activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
message: error.message,
},
});
}
}
/**
* Used for changing league and changing game type
*
* @memberof sagas/init
* @async
* @param {object} action
* @property {object} action
* @property {object} action.payload
*/
function* selectLeague(action) {
try {
const gameType = yield select(getGameType);
const user = yield select(getUser);
const selectedOdds = yield select(getSelectedOdds);
yield put({
type: SELECT_LEAGUE_SUCCESS,
payload: {
...action.payload,
clearLiveMatch: gameType && action.payload.type !== gameType,
},
});
if (selectedOdds?.length > 0) {
yield put({
type: TOGGLE_ODDS,
payload: { selectedOdds },
});
}
if (gameType && action.payload.type !== gameType) {
if (user) {
if (action.payload.type === GAME_TYPE.CLASSIC) {
yield put({
type: GET_ROUND,
payload: { selectedOdds, haveGameTypeChanged: action.payload.type !== gameType },
});
} else {
yield put({
type: GET_TURBO_ROUND,
payload: { selectedOdds, haveGameTypeChanged: action.payload.type !== gameType },
});
}
} else if (action.payload.type !== GAME_TYPE.CLASSIC) {
yield put({
type: GO_TO_LOGIN,
payload: {
loadRound: true,
},
});
}
}
} catch (error) {
yield put({
type: SHOW_ERROR_MODAL,
payload: {
activeModal: Constants.MODALS.GENERAL_ERROR,
message: error.message,
},
});
}
}
/**
*
*/
function* roundBets() {
let response;
try {
response = yield call(requestGet, `${Constants.API_URLS.ROUND_BETS}`, true);
if (response.status !== -1) {
const roundKeys = Object.keys(response.data);
for (let i = 0; i < roundKeys.length; i += 1) {
const roundKey = roundKeys[i];
const { roundId, coupons } = response.data[roundKey];
if (roundId > 0 && coupons.length > 0) {
yield put({
type: ADD_PLACED_BET_BULK,
payload: {
roundId,
coupons,
},
});
}
}
}
} catch (error) {
yield put({
type: SHOW_ERROR_MODAL,
payload: {
activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
message: error.message,
},
});
}
}
/**
*
*/
function* openBets() {
let response;
try {
response = yield call(requestGet, `${Constants.API_URLS.OPEN_BETS}`, true);
if (response.status !== -1) {
const clasicBets = response.data.bettingRoundClassic;
const clasicBetsLive = response.data.liveRoundClassic;
const tubroBets = response.data.bettingRoundTurbo;
const tubroBetsLive = response.data.liveRoundTurbo;
if (clasicBets > 0 || clasicBetsLive > 0) {
const clasicRoundResponse = yield call(requestGet, Constants.API_URLS.ROUND, true);
if (clasicBets > 0) {
yield put({
type: ADD_TICKET_TO_THE_COUNT,
payload: {
roundId: clasicRoundResponse.data.round.roundId,
gameType: GAME_TYPE.CLASSIC,
count: clasicBets,
},
});
yield put({
type: SCHEDULE_BET_COUNT,
payload: {
roundId: clasicRoundResponse.data.round.roundId,
gameType: GAME_TYPE.CLASSIC,
time: new Date(Date.parse(clasicRoundResponse.data.round.endDate)
+ 3000 + 1000 * clasicRoundResponse.data.roundResults.liveRoundDuration),
},
});
}
if (clasicBetsLive > 0) {
yield put({
type: ADD_TICKET_TO_THE_COUNT,
payload: {
roundId: clasicRoundResponse.data.roundResults.roundId,
gameType: GAME_TYPE.CLASSIC,
count: clasicBetsLive,
},
});
yield put({
type: SCHEDULE_BET_COUNT,
payload: {
roundId: clasicRoundResponse.data.roundResults.roundId,
gameType: GAME_TYPE.CLASSIC,
time: new Date(Date.parse(clasicRoundResponse.data.roundResults.liveEndDate) + 3000),
},
});
}
}
if (tubroBets > 0 || tubroBetsLive > 0) {
const turboRoundResponse = yield call(requestGet, Constants.API_URLS.KICK_OFF, true);
const endDate = turboRoundResponse.data.endDate;
if (endDate) {
yield put({
type: ADD_TICKET_TO_THE_COUNT,
payload: {
roundId: turboRoundResponse.data.roundId,
gameType: GAME_TYPE.TURBO,
count: tubroBets + tubroBetsLive,
},
});
yield put({
type: SCHEDULE_BET_COUNT,
payload: {
roundId: turboRoundResponse.data.roundId,
gameType: GAME_TYPE.TURBO,
time: new Date(Date.parse(endDate) + 3000),
},
});
}
}
}
} catch (error) {
yield put({
type: SHOW_ERROR_MODAL,
payload: {
activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
message: error.message,
},
});
}
}
/**
* @memberof sagas/init
* @async
* @returns {void}
*/
export default function* initSaga() {
yield takeEvery(GET_INIT, init);
yield takeEvery(GET_ROUND_SELECTIONS, roundSelections);
yield takeEvery(GET_TURBO_ROUND_SELECTIONS, turboRoundSelections);
yield takeEvery(SELECT_LEAGUE, selectLeague);
yield takeEvery(GET_OPEN_BETS, openBets);
yield takeEvery(GET_OPEN_BETS, roundBets);
}