import {
takeEvery, put, call, select,
} from 'redux-saga/effects';
/**
* @namespace sagas/placebet
*/
import Constants, { GAME_TYPE } from '../constants';
import { requestPost } from '../utils/request';
import {
UPDATE_BALANCE,
PLACEBET,
SET_PLACEBET_LOADER,
PLACEBET_SUCCESS,
SHOW_ERROR_MODAL,
PLACEBET_ERROR_LOGIN,
GET_LOYALTY,
SET_FREE_BETS,
SET_END_DATE,
SET_PLACED_BETS_RECORD,
SET_LAST_BET_ROUND,
SET_LAST_BET_ROUND_TURBO,
ADD_NEXT_ROUND_BET,
ADD_TICKET_TO_THE_COUNT,
SCHEDULE_BET_COUNT,
SET_LAST_TURBO_ROUND_PLAYED,
ADD_PLACED_BET,
} from '../reducers';
import { parsePlacedSelections, parseNum } from '../utils/parser';
import { getUser } from '../store/common';
import { getNumberOfBets, getPlacedBetsRecord } from '../store/tickets';
import {
getMarkets,
getGameType,
getSelectedLeague,
getHaveLiveMatches,
getRoundEnd,
getLiveMatchDuration,
} from '../store/bets';
import { getPlacedSelections, getPlacedSelectionsTurbo } from '../store/placebet';
import {
sortFreeBets,
addToPlacedBetsRecord,
updateBetCounter,
parseCouponData,
} from '../utils/common';
/**
* @memberof sagas/placebet
* @typedef "placebet/response.data"
* @type {object}
* @property {number} amount
* @property {number} bonusAmount
* @property {string} currency
*/
/**
* Placeing bet
*
* @memberof sagas/placebet
* @async
* @param {object} action
* @property {object} action
* @property {object} action.payload
* @property {string} action.payload.betData Parsed bet data
* (betType|league:match:selection$..|totalAmount or combinationType:stake&...&T:totalAmount)"
* @property {number} action.payload.round Round ID
* @property {number} action.payload.maxPotWin Maximum potential win
* @property {number|null} action.payload.freeBetId If free bets is placed, id of placed free bet
*
* @yields {select} getUser
* @yields {put} PLACEBET_ERROR_LOGIN
* @yields {put} SET_PLACEBET_LOADER
* @yields {select} getRoundId
* @yields {call} /bet/placebet
* @yields {put} SET_FREE_BETS
* @yields {put} UPDATE_BALANCE
* @yields {put} GET_LOYALTY
* @yields {select} getPlacedSelections
* @yields {select} getNumberOfBets
* @yields {select} getMarkets
* @yields {put} PLACEBET_SUCCESS
* @yields {put} SET_NUM_OF_BETS
* @yields {put} SHOW_ERROR_MODAL
*/
function* placebet(action) {
let response;
try {
const user = yield select(getUser);
if (!user) {
yield put({
type: PLACEBET_ERROR_LOGIN,
});
yield put({
type: SET_PLACEBET_LOADER,
payload: {
placebetAfterLogin: action.payload,
isLoadingPlaceBet: false,
placeBetErrorMgs: null,
},
});
return;
}
let betSelections = action.payload.odds;
let processedStake = action.payload.stake;
// filter out selections no stake was put on, ONLY SINGLE BET
if (action.payload.type === Constants.BET_TYPE_VALUES.SINGLE) {
let stakes = action.payload.stake.split('&');
stakes.pop(); // remove last (total) stake
const playedSelectionsIndexes = stakes.map((s) => parseInt(s.split(':')[0]));
const selectionIndexesObject = {};
playedSelectionsIndexes.map((x) => { selectionIndexesObject[x] = true; });
const betSelectionsArray = betSelections.split('$');
betSelections = betSelectionsArray.filter((s, i) => selectionIndexesObject[i + 1]).join('$');
// update stakes
stakes = action.payload.stake.split('&');
const lastStake = stakes[stakes.length - 1];
stakes.pop();
// update stake indexes because we removed some selections
stakes = stakes.map((s, i) => { const elems = s.split(':'); elems[0] = i + 1; return elems.join(':'); }).join('&');
processedStake = `${stakes}&${lastStake}`;
}
const data = `${action.payload.type}|${betSelections}|${processedStake}`;
yield put({
type: SET_PLACEBET_LOADER,
payload: {
isLoadingPlaceBet: true,
placebetAfterLogin: null,
placeBetErrorMgs: null,
},
});
const roundId = action.payload.roundId;
const gameType = yield select(getGameType);
const selectedLeague = yield select(getSelectedLeague);
const turbo = gameType === GAME_TYPE.TURBO;
response = yield call(
requestPost, Constants.API_URLS.PLACEBET,
{
betData: data,
round: roundId,
maxPotWin: action.payload.maxPotWin,
freeBetId: action.payload.freeBetId,
turbo,
newSplitBetPotentialWinCalculation:
action.payload.type === Constants.BET_TYPE_VALUES.SPLIT_COLUMN,
newSingleBetPotentialWinCalculation:
action.payload.type === Constants.BET_TYPE_VALUES.SINGLE,
}, true,
);
if (response.status === -1) {
yield put({
type: SET_PLACEBET_LOADER,
payload: {
placebetAfterLogin: null,
placeBetErrorMgs: response.error.message,
isLoadingPlaceBet: false,
},
});
} else {
yield put({
type: ADD_PLACED_BET,
payload: {
roundId,
couponData: parseCouponData(action.payload.type, betSelections, processedStake),
},
});
if (turbo) {
yield put({
type: SET_LAST_TURBO_ROUND_PLAYED,
payload: { roundId },
});
yield put({
type: SET_END_DATE,
payload: {
roundEnd: new Date(response.data.round.endDate),
showKickOff: true,
},
});
} else {
const isLive = yield select(getHaveLiveMatches);
if (isLive) {
yield put({
type: ADD_NEXT_ROUND_BET,
payload: {},
});
}
}
if (response.data.freeBets) {
yield put({
type: SET_FREE_BETS,
payload: {
freeBets: sortFreeBets(response.data.freeBets),
},
});
} else {
user.balance.amount = parseNum(response.data.amount);
user.balance.bonusAmount = parseNum(response.data.bonusAmount);
yield put({
type: UPDATE_BALANCE,
payload: {
user,
},
});
yield put({
type: GET_LOYALTY,
payload: {
isAfterPlacebet: true,
},
});
}
if (turbo) {
yield put({
type: SET_LAST_BET_ROUND_TURBO,
payload: roundId,
});
} else {
yield put({
type: SET_LAST_BET_ROUND,
payload: roundId,
});
}
let placedSelections = yield select(getPlacedSelections);
placedSelections = placedSelections[roundId] || null;
let placedSelectionsTurbo = yield select(getPlacedSelectionsTurbo);
placedSelectionsTurbo = placedSelectionsTurbo[roundId] || null;
let numberOfBets = yield select(getNumberOfBets);
let placedBetsRecord = yield select(getPlacedBetsRecord);
const markets = yield select(getMarkets);
placedBetsRecord = addToPlacedBetsRecord(placedBetsRecord, {
gameType,
pastWeek: selectedLeague.liveWeek || 0,
currentWeek: selectedLeague.week || 0,
});
numberOfBets = updateBetCounter(placedBetsRecord);
let filteredSelections = action.payload.placedSelection;
if (action.payload.type === 1) {
const stakes = action.payload.stake.split('&');
stakes.splice(-1, 1);
const realSelections = [];
for (let i = 0; i < stakes.length; i += 1) {
const bettedSelection = parseInt(stakes[i].split(':')[0]) - 1;
realSelections.push(filteredSelections[bettedSelection]);
}
filteredSelections = realSelections;
}
if (gameType === GAME_TYPE.TURBO) {
placedSelectionsTurbo = parsePlacedSelections(
filteredSelections,
placedSelectionsTurbo || {},
markets,
);
} else {
placedSelections = parsePlacedSelections(
filteredSelections,
placedSelections || {},
markets,
);
}
yield put({
type: ADD_TICKET_TO_THE_COUNT,
payload: {
roundId,
count: 1,
gameType,
},
});
yield put({
type: SET_PLACED_BETS_RECORD,
payload: {
numberOfBets,
placedBetsRecord,
},
});
let roundEndTime = gameType === GAME_TYPE.TURBO
? response.data.round.endDate : yield select(getRoundEnd);
const roundLiveDuration = gameType === GAME_TYPE.TURBO
? 5 : yield select(getLiveMatchDuration);
roundEndTime = new Date(Date.parse(roundEndTime) + (roundLiveDuration + 3) * 1000);
yield put({
type: SCHEDULE_BET_COUNT,
payload: {
roundId,
gameType,
time: roundEndTime,
},
});
yield put({
type: PLACEBET_SUCCESS,
payload: {
placedSelections,
placedSelectionsTurbo,
round: response.data.round,
turbo,
roundId,
},
});
}
} catch (error) {
yield put({
type: SHOW_ERROR_MODAL,
payload: {
activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
message: error.message,
},
});
}
}
/**
* @memberof sagas/placebet
* @async
* @returns {void}
*/
export default function* placebetSaga() {
yield takeEvery(PLACEBET, placebet);
}