'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.search = exports.ERR_API = exports.ERR_INVALID_SORT = exports.ERR_NO_VOCABULARY_SERVICE = exports.ERR_NO_RECORD_SERVICE = exports.SEARCH_REJECTED = exports.SEARCH_FULFILLED = exports.SEARCH_STARTED = exports.CREATE_EMPTY_SEARCH_RESULT = exports.SET_MOST_RECENT_SEARCH = 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);

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

var SET_MOST_RECENT_SEARCH = exports.SET_MOST_RECENT_SEARCH = 'SET_MOST_RECENT_SEARCH';
var CREATE_EMPTY_SEARCH_RESULT = exports.CREATE_EMPTY_SEARCH_RESULT = 'CREATE_EMPTY_SEARCH_RESULT';
var SEARCH_STARTED = exports.SEARCH_STARTED = 'SEARCH_STARTED';
var SEARCH_FULFILLED = exports.SEARCH_FULFILLED = 'SEARCH_FULFILLED';
var SEARCH_REJECTED = exports.SEARCH_REJECTED = 'SEARCH_REJECTED';

var ERR_NO_RECORD_SERVICE = exports.ERR_NO_RECORD_SERVICE = 'ERR_NO_RECORD_SERVICE';
var ERR_NO_VOCABULARY_SERVICE = exports.ERR_NO_VOCABULARY_SERVICE = 'ERR_NO_VOCABULARY_SERVICE';
var ERR_INVALID_SORT = exports.ERR_INVALID_SORT = 'ERR_INVALID_SORT';
var ERR_API = exports.ERR_API = 'ERR_API';

var findColumnByName = function findColumnByName(columns, columnName) {
  if (!columns) return null;

  for (var i = 0; i < columns.length; i += 1) {
    var column = columns[i];

    if (column.name === columnName) {
      return column;
    }
  }

  return null;
};

var getSortParam = function getSortParam(config, searchDescriptor, columnSetName) {
  var sortSpec = searchDescriptor.searchQuery.sort;

  var _sortSpec$split = sortSpec.split(' '),
      _sortSpec$split2 = _slicedToArray(_sortSpec$split, 2),
      sortColumnName = _sortSpec$split2[0],
      sortDir = _sortSpec$split2[1];

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

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

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

  return null;
};

var search = exports.search = function search(config, searchName, searchDescriptor) {
  var listType = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'common';
  var columnSetName = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'default';
  return function (dispatch, getState) {
    var recordType = searchDescriptor.recordType,
        vocabulary = searchDescriptor.vocabulary,
        csid = searchDescriptor.csid,
        subresource = searchDescriptor.subresource,
        searchQuery = searchDescriptor.searchQuery;


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

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

    var listTypeConfig = config.listTypes[listType];

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

    var recordTypeConfig = config.recordTypes[recordType];

    if (!recordTypeConfig) {
      return dispatch({
        type: SEARCH_REJECTED,
        payload: {
          code: ERR_NO_RECORD_SERVICE
        },
        meta: {
          searchName: searchName,
          searchDescriptor: searchDescriptor
        }
      });
    }

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

    if (!recordTypeServicePath) {
      return dispatch({
        type: SEARCH_REJECTED,
        payload: {
          code: ERR_NO_RECORD_SERVICE
        },
        meta: {
          searchName: searchName,
          searchDescriptor: searchDescriptor
        }
      });
    }

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

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

    // 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.rel === '' ||

    // A subresource query without a csid.
    typeof subresource !== 'undefined' && !searchDescriptor.csid) {
      return dispatch({
        type: CREATE_EMPTY_SEARCH_RESULT,
        meta: {
          listTypeConfig: listTypeConfig,
          searchName: searchName,
          searchDescriptor: searchDescriptor
        }
      });
    }

    var requestConfig = {
      params: {
        kw: searchQuery.kw,
        pgNum: searchQuery.p,
        pgSz: searchQuery.size,
        rtSbj: searchQuery.rel,
        wf_deleted: false
      }
    };

    if (searchQuery.sort) {
      var sortParam = getSortParam(config, searchDescriptor, columnSetName);

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

      requestConfig.params.sortBy = sortParam;
    }

    var pathParts = [recordTypeServicePath];

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

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

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

      pathParts.push(subresourceServicePath);
    }

    var 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(function (response) {
      return dispatch({
        type: SEARCH_FULFILLED,
        payload: response,
        meta: {
          searchName: searchName,
          searchDescriptor: searchDescriptor
        }
      });
    }, function (error) {
      return dispatch({
        type: SEARCH_REJECTED,
        payload: {
          code: ERR_API,
          error: error
        },
        meta: {
          searchName: searchName,
          searchDescriptor: searchDescriptor
        }
      });
    });
  };
};