'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.deselectResultItem = exports.setAllResultItemsSelected = exports.setResultItemSelected = exports.search = exports.clearSearchResults = exports.clearSelected = exports.DESELECT_RESULT_ITEM = exports.SET_RESULT_ITEM_SELECTED = exports.SET_ALL_RESULT_ITEMS_SELECTED = exports.SEARCH_REJECTED = exports.SEARCH_FULFILLED = exports.SEARCH_STARTED = exports.CREATE_EMPTY_SEARCH_RESULT = exports.SET_MOST_RECENT_SEARCH = exports.CLEAR_SEARCH_RESULTS = exports.CLEAR_SELECTED = undefined;

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var _get = require('lodash/get');

var _get2 = _interopRequireDefault(_get);

var _reducers = require('../reducers');

var _cspace = require('./cspace');

var _cspace2 = _interopRequireDefault(_cspace);

var _searchHelpers = require('../helpers/searchHelpers');

var _errorCodes = require('../constants/errorCodes');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const CLEAR_SELECTED = exports.CLEAR_SELECTED = 'CLEAR_SELECTED';
const CLEAR_SEARCH_RESULTS = exports.CLEAR_SEARCH_RESULTS = 'CLEAR_SEARCH_RESULTS';
const SET_MOST_RECENT_SEARCH = exports.SET_MOST_RECENT_SEARCH = 'SET_MOST_RECENT_SEARCH';
const CREATE_EMPTY_SEARCH_RESULT = exports.CREATE_EMPTY_SEARCH_RESULT = 'CREATE_EMPTY_SEARCH_RESULT';
const SEARCH_STARTED = exports.SEARCH_STARTED = 'SEARCH_STARTED';
const SEARCH_FULFILLED = exports.SEARCH_FULFILLED = 'SEARCH_FULFILLED';
const SEARCH_REJECTED = exports.SEARCH_REJECTED = 'SEARCH_REJECTED';
const SET_ALL_RESULT_ITEMS_SELECTED = exports.SET_ALL_RESULT_ITEMS_SELECTED = 'SET_ALL_RESULT_ITEMS_SELECTED';
const SET_RESULT_ITEM_SELECTED = exports.SET_RESULT_ITEM_SELECTED = 'SET_RESULT_ITEM_SELECTED';
const DESELECT_RESULT_ITEM = exports.DESELECT_RESULT_ITEM = 'DESELECT_RESULT_ITEM';

const getSortParam = (config, searchDescriptor, columnSetName) => {
  const sortSpec = searchDescriptor.getIn(['searchQuery', 'sort']);

  var _sortSpec$split = sortSpec.split(' '),
      _sortSpec$split2 = _slicedToArray(_sortSpec$split, 2);

  const sortColumnName = _sortSpec$split2[0],
        sortDir = _sortSpec$split2[1];


  if (sortDir && sortDir !== 'desc') {
    return null;
  }

  const column = (0, _get2.default)(config, ['recordTypes', searchDescriptor.get('recordType'), 'columns', columnSetName, sortColumnName]);

  if (column && column.sortBy) {
    return column.sortBy + (sortDir ? ' DESC' : '');
  }

  return null;
};

const clearSelected = exports.clearSelected = searchName => ({
  type: CLEAR_SELECTED,
  meta: {
    searchName
  }
});

const clearSearchResults = exports.clearSearchResults = searchName => ({
  type: CLEAR_SEARCH_RESULTS,
  meta: {
    searchName
  }
});

const search = exports.search = (config, searchName, searchDescriptor, listType = 'common', columnSetName = 'default') => (dispatch, getState) => {
  const recordType = searchDescriptor.get('recordType');
  const vocabulary = searchDescriptor.get('vocabulary');
  const csid = searchDescriptor.get('csid');
  const subresource = searchDescriptor.get('subresource');
  const searchQuery = searchDescriptor.get('searchQuery');

  if ((0, _reducers.isSearchPending)(getState(), searchName, searchDescriptor) || (0, _reducers.getSearchResult)(getState(), searchName, searchDescriptor) && !(0, _reducers.isSearchDirty)(getState(), searchName)) {
    // There's already a result for this search. Just set this search to be the most recent.

    dispatch({
      type: SET_MOST_RECENT_SEARCH,
      meta: {
        searchName,
        searchDescriptor
      }
    });

    return Promise.resolve();
  }

  const listTypeConfig = config.listTypes[listType];

  dispatch({
    type: SEARCH_STARTED,
    meta: {
      listTypeConfig,
      searchName,
      searchDescriptor
    }
  });

  const recordTypeConfig = config.recordTypes[recordType];

  if (!recordTypeConfig) {
    dispatch({
      type: SEARCH_REJECTED,
      payload: {
        code: _errorCodes.ERR_UNKNOWN_RECORD_TYPE
      },
      meta: {
        searchName,
        searchDescriptor
      }
    });

    return Promise.reject();
  }

  const recordTypeServicePath = (0, _get2.default)(recordTypeConfig, ['serviceConfig', 'servicePath']);

  if (!recordTypeServicePath) {
    dispatch({
      type: SEARCH_REJECTED,
      payload: {
        code: _errorCodes.ERR_UNKNOWN_RECORD_TYPE
      },
      meta: {
        searchName,
        searchDescriptor
      }
    });

    return Promise.reject();
  }

  const vocabularyServicePath = vocabulary ? (0, _get2.default)(recordTypeConfig, ['vocabularies', vocabulary, 'serviceConfig', 'servicePath']) : null;

  if (vocabulary && !vocabularyServicePath) {
    dispatch({
      type: SEARCH_REJECTED,
      payload: {
        code: _errorCodes.ERR_UNKNOWN_VOCABULARY
      },
      meta: {
        searchName,
        searchDescriptor
      }
    });

    return Promise.reject();
  }

  // Check for conditions where we just want to create an empty result.
  // These happen when a new record is being created.

  if (
  // A related record search for an empty csid.

  searchQuery.get('rel') === '' ||

  // A subresource query without a csid.

  typeof subresource !== 'undefined' && !searchDescriptor.get('csid')) {
    dispatch({
      type: CREATE_EMPTY_SEARCH_RESULT,
      meta: {
        listTypeConfig,
        searchName,
        searchDescriptor
      }
    });

    return Promise.resolve();
  }

  const nxql = (0, _searchHelpers.advancedSearchConditionToNXQL)(recordTypeConfig.fields, searchQuery.get('as'));

  const requestConfig = {
    params: {
      as: nxql ? `(${nxql})` : undefined,
      csid: searchQuery.get('csid'),
      doctype: searchQuery.get('doctype'),
      kw: searchQuery.get('kw'),
      mkRtSbj: searchQuery.get('mkRtSbj'),
      pgNum: searchQuery.get('p'),
      pgSz: searchQuery.get('size'),
      rtSbj: searchQuery.get('rel'),
      rtPredicate: searchQuery.get('relType'),
      sn: searchQuery.get('sn'), // accounts screen name
      wf_deleted: false
    }
  };

  if (searchQuery.get('sort')) {
    const sortParam = getSortParam(config, searchDescriptor, columnSetName);

    if (!sortParam) {
      dispatch({
        type: SEARCH_REJECTED,
        payload: {
          code: _errorCodes.ERR_INVALID_SORT
        },
        meta: {
          searchName,
          searchDescriptor
        }
      });

      return Promise.reject();
    }

    requestConfig.params.sortBy = sortParam;
  }

  const pathParts = [recordTypeServicePath];

  if (vocabularyServicePath) {
    pathParts.push(vocabularyServicePath);
    pathParts.push('items');
  }

  if (csid) {
    pathParts.push(csid);
  }

  if (subresource) {
    const subresourceConfig = config.subresources[subresource];
    const subresourceServicePath = subresourceConfig.serviceConfig.servicePath;

    pathParts.push(subresourceServicePath);
  }

  const path = pathParts.join('/');

  return (0, _cspace2.default)().read(path, requestConfig)
  // Insert an artificial delay for testing.
  // .then(response => new Promise((resolve) => {
  //   window.setTimeout(() => {
  //     resolve(response);
  //   }, 1000);
  // }))
  .then(response => dispatch({
    type: SEARCH_FULFILLED,
    payload: response,
    meta: {
      listTypeConfig,
      searchName,
      searchDescriptor
    }
  })).catch(error => dispatch({
    type: SEARCH_REJECTED,
    payload: {
      code: _errorCodes.ERR_API,
      error
    },
    meta: {
      searchName,
      searchDescriptor
    }
  }));
};

const setResultItemSelected = exports.setResultItemSelected = (config, searchName, searchDescriptor, listType = 'common', index, isSelected) => {
  const listTypeConfig = config.listTypes[listType];

  return {
    type: SET_RESULT_ITEM_SELECTED,
    payload: isSelected,
    meta: {
      listTypeConfig,
      searchName,
      searchDescriptor,
      index
    }
  };
};

const setAllResultItemsSelected = exports.setAllResultItemsSelected = (config, searchName, searchDescriptor, listType = 'common', isSelected, filter) => {
  const listTypeConfig = config.listTypes[listType];

  return {
    type: SET_ALL_RESULT_ITEMS_SELECTED,
    payload: isSelected,
    meta: {
      filter,
      listTypeConfig,
      searchName,
      searchDescriptor
    }
  };
};

const deselectResultItem = exports.deselectResultItem = (searchName, csid) => ({
  type: DESELECT_RESULT_ITEM,
  meta: {
    searchName,
    csid
  }
});