import store from '../store';
import {userService} from 'services/';
import {
  getAuthKey,
  setAuthKey,
  deleteSavedLayout,
  deleteAuthKey,
  handleAPIResponse
} from 'utils/session';
import { checkResponseStatus } from 'utils/watchlists';
import { playAlertAudio } from '../components/utils/AlertAudio';


export const POPOUT_SELECT_WATCHLIST = 'POPOUT_SELECT_WATCHLIST';
export const WIDGET_SELECT_WATCHLIST = 'WIDGET_SELECT_WATCHLIST';
export function selectWatchlist(widgetId, watchlistId, isPopout = false) {
  const type = isPopout ? POPOUT_SELECT_WATCHLIST : WIDGET_SELECT_WATCHLIST;
  store.dispatch({
    type,
    watchlistId,
    widgetId
  });
  bzTrack.track('Watchlist: Selected', {
    widgetId: widgetId,
    watchlistId: watchlistId
  });
}


export const ADD_WATCHLIST = 'ADD_WATCHLIST';
export function addWatchlist(name, tickers, widgetId, isPopout = false) {
  userService.createWatchlist(name, tickers).then(watchlist => {
    const addedTickers = [];
    for (const alert of Object.values(watchlist.alerts)) {
      addedTickers.push({symbol: alert.alert_name, id: alert.alert_id});
    }

    store.dispatch({
      type: ADD_WATCHLIST,
      id: watchlist.portfolio_id,
      name: watchlist.portfolio_name,
      tickers: addedTickers
    });

    if (widgetId !== null) {
      // Move user to new watchlist.
      selectWatchlist(widgetId, watchlist.portfolio_id, isPopout);
    }

    bzTrack.track('Watchlist: Created', {
      name: name,
      tickers: tickers
    });
  });
}


export const REQUEST_WATCHLISTS = 'REQUEST_WATCHLISTS';
export function requestWatchlists() {
  return {
    type: REQUEST_WATCHLISTS
  };
}
export function getWatchlists() {
  return dispatch => {
    dispatch(requestWatchlists());

    const authKey = getAuthKey();

    return fetch(`${process.env.SERVICES_ROOT}/services/watchlist/bzuser/portfolio?status=enabled`, {
      headers: {'accept': 'application/json', 'content-type': 'application/json', 'x-device-key': authKey},
      method: 'get'
    })
    .then(checkResponseStatus)
    .then(json =>
      dispatch(requestWatchlists(json))
    );
  };
}

export const RECEIVE_WATCHLISTS = 'RECEIVE_WATCHLISTS';
export function receiveWatchlists(watchlists) {
  return {
    type: RECEIVE_WATCHLISTS,
    watchlists
  };
}

export const WATCHLIST_CREATED = 'WATCHLIST_CREATED';
export function watchlistCreated(watchlist) {
  return {
    type: WATCHLIST_CREATED,
    watchlist
  };
}

export const WATCHLIST_UPDATED = 'WATCHLIST_UPDATED';
export function watchlistUpdated(watchlist) {
  return {
    type: WATCHLIST_UPDATED,
    watchlist
  };
}

export const WATCHLIST_DELETED = 'WATCHLIST_DELETED';
export function watchlistDeleted(watchlist) {
  return {
    type: WATCHLIST_DELETED,
    watchlist
  };
}

export const CREATE_WATCHLIST = 'CREATE_WATCHLIST';
export function createWatchlist(name, symbols = []) {
  return dispatch => {
    dispatch({type: CREATE_WATCHLIST});

    const authKey = getAuthKey();
    const data = {
      portfolio_name: name,
      status: true,
      send_summary: false,
      alerts: map(symbols, symbol => {
        return {
          alert_name: symbol,
          send_realtime: false,
          status: true,
          type: 'ticker'
        };
      })
    };

    return fetch(`${process.env.SERVICES_ROOT}/services/watchlist/bzuser/portfolio`, {
      headers: {'accept': 'application/json', 'content-type': 'application/json', 'x-device-key': authKey},
      body: JSON.stringify(data),
      method: 'post'
    })
    .then(checkResponseStatus)
    .then(json =>
      // I'm sure you can hear my audible laughter -- ZAC
      dispatch(receiveWatchlists(data.data[Object.keys(data.data)[0]]))
    );
  };
}

export const UPDATE_WATCHLIST = 'UPDATE_WATCHLIST';
export function updateWatchlist(watchlistId, name) {
  return dispatch => {
    dispatch({type: UPDATE_WATCHLIST, watchlistId});

    const authKey = getAuthKey();
    const data = {
      portfolio_id: watchlistId,
      portfolio_name: name
    };

    return fetch(`${process.env.SERVICES_ROOT}/services/watchlist/bzuser/portfolio/${watchlistId}/`, {
      headers: {'accept': 'application/json', 'content-type': 'application/json', 'x-device-key': authKey},
      body: JSON.stringify(data),
      method: 'put'
    })
    .then(checkResponseStatus)
    .then(data =>
      dispatch(watchlistUpdated(data))
    );
  };
}

export const DELETE_WATCHLIST = 'DELETE_WATCHLIST';
export function deleteWatchlist(watchlistId, widgetId, isPopout = false) {
  function deleteWatchlistHelper(watchlistId) {
    return dispatch => {
      dispatch({
        type: DELETE_WATCHLIST,
        watchlistId
      });
      const authKey = getAuthKey();
      return fetch(`${process.env.SERVICES_ROOT}/services/watchlist/bzuser/portfolio/${watchlistId}/`, {
        headers: {
          'accept': 'application/json',
          'content-type': 'application/json',
          'x-device-key': authKey
        },
        method: 'delete'
      })
      .then(checkResponseStatus);
    };
  }

  return store.dispatch((dispatch, getState) => {
    const watchlist = getState().watchlists.getIn(['watchlists', watchlistId]);
    if (widgetId !== null) {
      // Move user back to first watchlist.
      const watchlistIds = Object.keys(getState().watchlists.get('watchlists').toJS());
      let idToChangeTo = null;
      if (watchlistIds.length > 1) {
        idToChangeTo = watchlistIds[0];
        if (idToChangeTo === watchlistId) {
          idToChangeTo = watchlistIds[1];
        }
      }
      selectWatchlist(widgetId, idToChangeTo, isPopout);
    }
    dispatch(deleteWatchlistHelper(watchlistId)).then(success => {
      bzTrack.track('Watchlist: Deleted');
      return success;
    }).catch(error => {
      // If there was an error in deleting the watchlist add it back to the store
      // and continue throwing the error.
      dispatch(addWatchlist(watchlist.get('id'), watchlist.get('name'), watchlist.get('tickers')));
      throw error;
    });
  });
}

export const WATCHLIST_WIDGET_TOGGLE_DISPLAY = 'WATCHLIST_WIDGET_TOGGLE_DISPLAY';
export const WATCHLIST_POPOUT_TOGGLE_DISPLAY = 'WATCHLIST_POPOUT_TOGGLE_DISPLAY';
export function toggleDisplay(widgetId, display, isPopout) {
  const type = isPopout ? WATCHLIST_POPOUT_TOGGLE_DISPLAY : WATCHLIST_WIDGET_TOGGLE_DISPLAY;
  store.dispatch({
    type,
    display,
    widgetId
  });
  bzTrack.track('Watchlist: Toggled Display', {section: display});
}


export const LOAD_WATCHLISTS = 'LOAD_WATCHLISTS';
export function loadWatchlistState(watchlists) {
  store.dispatch({
    type: LOAD_WATCHLISTS,
    state: watchlists
  });
}

export const ADD_TICKER_TO_WATCHLIST = 'ADD_TICKER_TO_WATCHLIST';
export function addTickerToWatchlist(watchlistId, ticker) {
  userService.addWatchlistSymbol(watchlistId, ticker).then(ticker => {
    store.dispatch({
      type: ADD_TICKER_TO_WATCHLIST,
      watchlistId,
      ticker
    });

    bzTrack.track('Watchlist: Ticker Added', {
      watchlistId: watchlistId,
      ticker: ticker
    });
  });
}

export const ADD_TICKERS_TO_WATCHLIST = 'ADD_TICKERS_TO_WATCHLIST';
export function addTickersToWatchlist(watchlistId, tickers) {
  userService.addWatchlistSymbols(watchlistId, tickers).then(tickers => {
    store.dispatch({
      type: ADD_TICKERS_TO_WATCHLIST,
      watchlistId,
      tickers
    });

    bzTrack.track('Watchlist: Tickers Added', {
      watchlistId: watchlistId,
      tickers: tickers
    });
  });
}

export const REMOVE_TICKER_FROM_WATCHLIST = 'REMOVE_TICKER_FROM_WATCHLIST';
export function removeTickerFromWatchlist(watchlistId, tickerId) {
  userService.deleteWatchlistSymbol(tickerId).then(ticker => {
    store.dispatch({
      type: REMOVE_TICKER_FROM_WATCHLIST,
      watchlistId,
      tickerId
    });
  });

  bzTrack.track('Watchlist: Ticker Removed', {
    watchlistId,
    tickerId
  });
}

export const TOGGLE_TICKER_ALERT = 'TOGGLE_TICKER_ALERT';
export function toggleAlert(tickerId, portfolioId, enabled) {
  store.dispatch({
    type: TOGGLE_TICKER_ALERT,
    name: 'emailAlertsEnabled',
    update: enabled,
    watchlistId: portfolioId,
    tickerId
  });

  userService.updateWatchlistAlert(tickerId, enabled, null).then(ticker => {
    // Don't have to do anything because the UI has already been updated
  }).catch(error => {
    // There has been an error, so undo the UI change performed earlier and handle error
    store.dispatch({
      type: TOGGLE_TICKER_ALERT,
      name: 'emailAlertsEnabled',
      update: !enabled,
      watchlistId: portfolioId,
      tickerId
    });
  });

  bzTrack.track('Watchlist Alerts: Email Toggle', {
    enabled: enabled,
    tickerId: tickerId
  });
}

export const TOGGLE_TICKER_ALERTS = 'TOGGLE_TICKER_ALERTS';
export function toggleAlerts(tickerIds, portfolioId, enabled) {
  store.dispatch({
    type: TOGGLE_TICKER_ALERTS,
    name: 'emailAlertsEnabled',
    update: enabled,
    watchlistId: portfolioId,
    tickerIds
  });

  userService.updateWatchlistAlerts(tickerIds, enabled, null).then(tickers => {
    // Don't need to update state, already done by default
  }).catch(error => {
    // An error has occured, so undo the change to state because it wasn't updated
    store.dispatch({
      type: TOGGLE_TICKER_ALERTS,
      name: 'emailAlertsEnabled',
      update: !enabled,
      watchlistId: tickers[0].portfolio_id,
      tickerIds
    });
  });

  for (const tickerId of tickerIds) {
    bzTrack.track('Watchlist Alerts: Email Toggle', {
      enabled: enabled,
      tickerId: tickerId
    });
  }
}

export const CHANGE_TICKER_SOUND = 'CHANGE_TICKER_SOUND';
export function changeSound(tickerId, sound) {
  playAlertAudio(sound);
  userService.updateWatchlistAlert(tickerId, null, sound).then(ticker => {
    store.dispatch({
      type: CHANGE_TICKER_SOUND,
      name: 'sound',
      update: sound,
      watchlistId: ticker.portfolio_id,
      tickerId
    });
  });

  bzTrack.track('Watchlist Alerts: Audio Toggle', {
    sound: sound,
    tickerId: tickerId
  });
}

export const CHANGE_TICKER_SOUNDS = 'CHANGE_TICKER_SOUNDS';
export function changeSounds(tickerIds, sound) {
  playAlertAudio(sound);
  userService.updateWatchlistAlerts(tickerIds, null, sound).then(tickers => {
    store.dispatch({
      type: CHANGE_TICKER_SOUNDS,
      name: 'sound',
      update: sound,
      watchlistId: tickers[0].portfolio_id,
      tickerIds
    });
  });

  for (const tickerId of tickerIds) {
    bzTrack.track('Watchlist Alerts: Audio Toggle', {
      sound: sound,
      tickerId: tickerId
    });
  }
}

