import {
  ADD_TICKER_TO_WATCHLIST,
  ADD_TICKERS_TO_WATCHLIST,
  REMOVE_TICKER_FROM_WATCHLIST,
  RECEIVE_WATCHLISTS,
  REQUEST_WATCHLISTS,
  ADD_WATCHLIST,
  DELETE_WATCHLIST,
  LOAD_WATCHLISTS,
  TOGGLE_TICKER_ALERT,
  TOGGLE_TICKER_ALERTS,
  CHANGE_TICKER_SOUND,
  CHANGE_TICKER_SOUNDS
} from 'actions/watchlists';
import Immutable from 'immutable';
import forEach from 'lodash/forEach';
import map from 'lodash/map';

const Watchlist = new Immutable.Record({
  id: null,
  name: null,
  tickers: new Immutable.List()
});

const WatchlistList = new Immutable.Record({
  isLoading: true,
  watchlists: new Immutable.Map()
});

const WatchlistTicker = new Immutable.Record({
  id: null,
  symbol: null,
  emailAlertsEnabled: false
});

export default function watchlistsReducer(state = new WatchlistList(), action) {
  switch (action.type) {
  case ADD_WATCHLIST:
    const tickerRecords = [];
    for (const ticker of action.tickers) {
      tickerRecords.push(new WatchlistTicker(ticker));
    }
    const newWatchlist = new Watchlist({name: action.name, tickers: new Immutable.List(tickerRecords), id: action.id});
    const whatever = state.setIn(['watchlists', action.id], newWatchlist);
    return whatever;
  case DELETE_WATCHLIST:
    return state.set('watchlists', state.get('watchlists').delete(action.watchlistId));
  case LOAD_WATCHLISTS:
    return new WatchlistList(Immutable.fromJS({watchlists: action.state}));
  case REQUEST_WATCHLISTS:
    return state.set('isLoading', true);
  case RECEIVE_WATCHLISTS:
    return state.set('isLoading', false).set('watchlists', Immutable.fromJS(action.watchlists));
  case ADD_TICKER_TO_WATCHLIST:
    return state.setIn(['watchlists', action.watchlistId, 'tickers'], state.getIn(['watchlists', action.watchlistId, 'tickers']).push(new WatchlistTicker(action.ticker)));
  case ADD_TICKERS_TO_WATCHLIST:
    const tickerList = [];
    for (const symbol of action.tickers) {
      tickerList.push(new WatchlistTicker(symbol));
    }
    return state.updateIn(['watchlists', action.watchlistId, 'tickers'], (list) => list.concat(tickerList));
  case TOGGLE_TICKER_ALERT:
  case CHANGE_TICKER_SOUND:
    let symbol = state.getIn(['watchlists', action.watchlistId, 'tickers']).find(t => t.get('id') === action.tickerId);

    if (!symbol) {
      return state;
    }
    symbol = symbol.get('symbol');

    return state.update('watchlists', lists => lists.map(watchlist => {
      const tickerIndex = watchlist.get('tickers').findIndex(t => t.get('symbol') === symbol);
      if (tickerIndex === -1) {
        return watchlist;
      }
      return watchlist.setIn(['tickers', tickerIndex, action.name], action.update);
    }));
  case TOGGLE_TICKER_ALERTS:
  case CHANGE_TICKER_SOUNDS:
    let newState = state;
    for (const tickerId of action.tickerIds) {
      let symbol = newState.getIn(['watchlists', action.watchlistId, 'tickers']).find(t => t.get('id') === tickerId);

      if (!symbol) {
        continue;
      }
      symbol = symbol.get('symbol');

      newState = newState.update('watchlists', lists => lists.map(watchlist => {
        const tickerIndex = watchlist.get('tickers').findIndex(t => t.get('symbol') === symbol);
        if (tickerIndex === -1) {
          return watchlist;
        }
        return watchlist.setIn(['tickers', tickerIndex, action.name], action.update);
      }));
    }
    return newState;
  case REMOVE_TICKER_FROM_WATCHLIST:
    const watchlist = state.getIn(['watchlists', action.watchlistId, 'tickers']);
    return state.setIn(['watchlists', action.watchlistId, 'tickers'], watchlist.delete(watchlist.findIndex(t => t.get('id') === action.tickerId)));
  default:
    return state;
  }
}
