import { combineReducers } from 'redux';

import { Action } from 'mweb/common/actions/root';
import {
  GAMES_DATA_REINITIALIZED_ACTION_TYPE,
  GAMES_DATA_PAGE_LOADED_ACTION_TYPE,
} from 'mweb/common/actions/data/games';
import { CHANNELS_DATA_PAGE_LOADED_ACTION_TYPE } from 'mweb/common/actions/data/channels';
import { EVENTS_DATA_EVENT_LOADED_ACTION_TYPE } from 'mweb/common/actions/data/events';

export interface GameDetails {
  readonly id: string;
  readonly name: string;
  readonly displayName: string;
  readonly boxArtURL: string;
  readonly viewersCount: number;
}

export interface GameDetailsMap {
  readonly [gameName: string]: GameDetails;
}

export interface GamesLoadStatus {
  readonly lastGameCursor: string | null;
  readonly lastInitTime: number;
}

const DEFAULT_GAMES_LOAD_STATUS: GamesLoadStatus = {
  lastGameCursor: null,
  lastInitTime: 0,
};

interface GameAliasMap {
  readonly [gameAlias: string]: string;
}

export interface GamesState {
  readonly gamesLoadStatus: GamesLoadStatus;
  readonly gameDetails: GameDetailsMap;
  readonly gameNameLookup: GameAliasMap;
}

export function gamesLoadStatus(
  state: GamesLoadStatus = DEFAULT_GAMES_LOAD_STATUS,
  action: Action,
): GamesLoadStatus {
  switch (action.type) {
    case GAMES_DATA_REINITIALIZED_ACTION_TYPE:
      return DEFAULT_GAMES_LOAD_STATUS;
    case GAMES_DATA_PAGE_LOADED_ACTION_TYPE:
      return {
        lastGameCursor: action.payload.lastGameCursor,
        lastInitTime: state.lastInitTime || new Date().valueOf(),
      };
    default:
      return state;
  }
}

export function gameDetails(
  state: GameDetailsMap = {},
  action: Action,
): GameDetailsMap {
  switch (action.type) {
    case GAMES_DATA_REINITIALIZED_ACTION_TYPE:
      return {};
    case GAMES_DATA_PAGE_LOADED_ACTION_TYPE:
      return {
        ...state,
        ...action.payload.gameDetails,
      };
    case EVENTS_DATA_EVENT_LOADED_ACTION_TYPE:
    case CHANNELS_DATA_PAGE_LOADED_ACTION_TYPE:
      if (!action.payload.game) {
        return state;
      }
      return {
        ...state,
        [action.payload.game.name]: {
          ...state[action.payload.game.name],
          ...action.payload.game,
        },
      };
    default:
      return state;
  }
}

export function gameNameLookup(
  state: GameAliasMap = {},
  action: Action,
): GameAliasMap {
  switch (action.type) {
    case CHANNELS_DATA_PAGE_LOADED_ACTION_TYPE:
      if (!action.payload.game) {
        return state;
      }
      const gameName = action.payload.game.name;
      return {
        ...state,
        [action.payload.gameAliasUsed]: gameName,
      };
    default:
      return state;
  }
}

export function buildGamesReducer(): (
  state: GamesState | undefined,
  action: Action,
) => GamesState {
  return combineReducers<GamesState>({
    gamesLoadStatus,
    gameDetails,
    gameNameLookup,
  });
}
