'use strict';

var _regenerator;

function _load_regenerator() {
  return _regenerator = _interopRequireDefault(require('babel-runtime/regenerator'));
}

var index = function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(component, scopePath) {
    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.prev = 0;
            _context.next = 3;
            return (_serverlessIndex || _load_serverlessIndex()).default.initializeIndex(scopePath);

          case 3:
            indexInstance = _context.sent;
            return _context.abrupt('return', addToLocalIndex(component));

          case 7:
            _context.prev = 7;
            _context.t0 = _context['catch'](0);

            (_logger || _load_logger()).default.error(`search.indexer found an issue while indexing. Error: ${_context.t0}`);
            console.warn(_context.t0); // eslint-disable-line // TODO - handle this error
            return _context.abrupt('return', Promise.resolve(component));

          case 12:
          case 'end':
            return _context.stop();
        }
      }
    }, _callee, this, [[0, 7]]);
  }));

  return function index(_x2, _x3) {
    return _ref.apply(this, arguments);
  };
}();

var indexAll = function () {
  var _ref2 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(path, components) {
    var results;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            if (components) {
              _context2.next = 2;
              break;
            }

            return _context2.abrupt('return', Promise.reject('The scope is empty'));

          case 2:
            (_logger || _load_logger()).default.debug(`indexing all, scope path ${path}`);
            _context2.next = 5;
            return (_serverlessIndex || _load_serverlessIndex()).default.initializeIndex(path);

          case 5:
            indexInstance = _context2.sent;

            (_serverlessIndex || _load_serverlessIndex()).default.deleteDb(path);
            results = addAllToLocalIndex(components);
            return _context2.abrupt('return', Promise.resolve(results));

          case 9:
          case 'end':
            return _context2.stop();
        }
      }
    }, _callee2, this);
  }));

  return function indexAll(_x4, _x5) {
    return _ref2.apply(this, arguments);
  };
}();

var _stream;

function _load_stream() {
  return _stream = require('stream');
}

var _porterStemmer;

function _load_porterStemmer() {
  return _porterStemmer = require('porter-stemmer');
}

var _component;

function _load_component() {
  return _component = _interopRequireDefault(require('../consumer/component'));
}

var _serverlessIndex;

function _load_serverlessIndex() {
  return _serverlessIndex = _interopRequireDefault(require('./serverless-index'));
}

var _logger;

function _load_logger() {
  return _logger = _interopRequireDefault(require('../logger/logger'));
}

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

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

var stem = function stem(sentence) {
  return sentence.split(' ').map((_porterStemmer || _load_porterStemmer()).stemmer).join(' ');
};
var indexInstance = void 0;

function tokenizeStr(str) {
  return str.trim().split(/(?=[A-Z])/).join(' ').toLowerCase().split(/ |_|-/).join(' ');
}

/**
 * returns the first sentence of the description.
 * @param {string} desc
 * @return {string}
 */
function minimizeDescription() {
  var desc = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

  return desc.split(/\.|;/)[0]; // split by a dot or a semicolon
}

function prepareDoc(docs, component) {
  var name = component.name;
  var tokenizedName = tokenizeStr(name);
  var functionNames = docs.map(function (doc) {
    return doc.name;
  }).join(' ');
  var minDescription = docs.map(function (doc) {
    return minimizeDescription(doc.description);
  }).join(' ');
  return {
    id: name,
    name,
    tokenizedName,
    stemmedName: stem(tokenizedName),
    functionNames,
    tokenizedFunctionNames: tokenizeStr(functionNames),
    description: docs.map(function (doc) {
      return doc.description;
    }).join(' '),
    minDescription,
    stemmedMinDescription: stem(minDescription)
  };
}

function addAllToLocalIndex(components) {
  return new Promise(function (resolve) {
    var docs = components.map(function (component) {
      return prepareDoc(component.docs, component);
    });
    var docStream = new (_stream || _load_stream()).Readable({ objectMode: true });
    // $FlowFixMe: a flow bug. Stream can be an object as well when objectMode is true
    docs.map(function (doc) {
      return docStream.push(doc);
    });
    docStream.push(null);
    docStream.pipe(indexInstance.defaultPipeline()).pipe(indexInstance.add()).on('finish', function () {
      resolve('The indexing has been completed');
    });
  });
}

function addToLocalIndex(component) {
  return new Promise(function (resolve) {
    var doc = prepareDoc(component.docs, component);
    var docStream = new (_stream || _load_stream()).Readable({ objectMode: true });
    // $FlowFixMe: a flow bug. Stream can be an object as well when objectMode is true
    docStream.push(doc);
    docStream.push(null);
    docStream.pipe(indexInstance.defaultPipeline()).pipe(indexInstance.add()).on('finish', function () {
      resolve(component);
    });
  });
}

module.exports = {
  index,
  indexAll,
  tokenizeStr,
  stem
};