import map from 'lodash/map';
import filter from 'lodash/filter';
import sortBy from 'lodash/sortBy';
import includes from 'lodash/includes';
import slice from 'lodash/slice';
import fetch from 'isomorphic-fetch';

export const REQUEST_CHANNELS = 'REQUEST_CHANNELS';
function requestChannels() {
  return {
    type: REQUEST_CHANNELS
  };
}

export const REQUEST_SOURCES = 'REQUEST_SOURCES';
function requestSources() {
  return {
    type: REQUEST_SOURCES
  };
}

/**
 * Given a JSON API response of news channels, return the Redux action.
 * Does some transforms to format channels the way we expect in our state.
 *
 * @param  {Object} json BZ API response
 * @return {Action}      Redux action
 */
export const RECEIVE_CHANNELS = 'RECEIVE_CHANNELS';
function receiveChannels(json) {
  let allChannels = map(json.data, (channel) => ({
    id: channel.channel_id,
    name: channel.channel_name,
    tids: map(channel.tids, (t) => parseInt(t.tid, 10))
  }));
  allChannels = sortBy(allChannels, 'name');

  // Business need => Market Moving Exclusives at the top of the list
  for (let i = 0; i < allChannels.length; i++) {
    if (allChannels[i].id === 'exclusives-premiere') {
      allChannels = [allChannels[i], ...slice(allChannels, 0, i), ...slice(allChannels, i + 1)];
    }
  }

  return {
    type: RECEIVE_CHANNELS,
    channels: allChannels
  };
}

/**
 * Given a JSON API response of story sources, return the Redux action.
 * Does some transforms to format sources the way we expect in our state.
 *
 * @param  {Object} json BZ API response
 * @return {Action}      Redux action
 */
export const RECEIVE_SOURCES = 'RECEIVE_SOURCES';
function receiveSources(json) {
  let sources = filter(json.types, (source) => !includes(json.pr_types, source.type) && source.type !== 'bzsyndicatefeed');

  // must convert .type (as it comes from the API) to .id
  map(sources, (source) => { source.id = source.type; delete source.type; });

  sources.push({
    name: 'Press Releases',
    id: 'pr_story', description:
    'Feed of company Press Releases'
  });

  sources = sortBy(sources, 'name');

  return {
    type: RECEIVE_SOURCES,
    sources: sources,
    pressReleaseTypes: json.pr_types
  };
}

/**
 * Makes the request to BZ for news channels, dispatching actions as it goes.
 *
 * @return {Promise}
 */
export function fetchChannels() {
  return dispatch => {
    // Let components know we're starting our request
    dispatch(requestChannels());

    return fetch(process.env.SERVICES_ROOT + '/services/watchlist/bzuser/channel/', {
      headers: {
        'accept': 'application/json',
        'x-device-key': localStorage.authKey,
        'content-type': 'application/json'
      },
      method: 'get'
    })
    .then(response => response.json())
    .then(json =>
      // Let components know we're done
      dispatch(receiveChannels(json))
    );
  };
}

/**
 * Makes the request to BZ for story sources, dispatching actions as it goes.
 *
 * @return {Promise}
 */
export function fetchSources() {
  return dispatch => {
    // Let components know we're starting our request
    dispatch(requestSources());

    return fetch('https://www.benzinga.com/ajax-cache/content-types-for-pro', {
      headers: {'accept': 'application/json'},
      method: 'get'
    })
    .then(response => response.json())
    .then(json =>
      // Let components know we're done
      dispatch(receiveSources(json))
    );
  };
}

export const SELECT_CHANNEL = 'SELECT_CHANNEL';
export function selectChannel(channel) {
  return {
    type: SELECT_CHANNEL,
    channel
  };
}

export const SELECT_SOURCE = 'SELECT_SOURCE';
export function selectSource(source) {
  return {
    type: SELECT_SOURCE,
    source
  };
}
