'use strict';
const config = require('config'),
  _ = require('lodash'),
  Promise = require('bluebird'),
  request = Promise.promisifyAll(require('request')),
  parse = require('../../parse'),
  apps = require('../../db/apps'),
  log = require('../../logger');

exports.init = function init(env) {
  return apps
    .init('code')
    .then((ret) => {
      env.apps = ret;
      return env;
    });
};

function getSmaliQuery(query) {
  let queryObj = parse(query);
  const lines = [];
  if (queryObj instanceof Array === false) {
    queryObj = [queryObj];
  }
  _.forEach(queryObj, (v) => {
    let line = '';
    _.forEach(v.attributes, (attrib) => {
      if (attrib.name.toLowerCase() === 'class') {
        line += 'L' + attrib.value.replace(/\./g, '/');
      }
      else if (attrib.name.toLowerCase() === 'method') {
        line += ';->' + attrib.value;
      }
    });
    if (line !== '') {
      lines.push(line);
    }
  });
  return lines;
}

exports.find = function find(env, query, options) {
  // If query is not specified, return everything in scope
  if (!query) {
    return Promise.resolve(options.scope);
  }
  const codeQueries = getSmaliQuery(query);
  // search the code collection in Solr
  function clientError(e) {
    return e.code >= 400 && e.code < 500;
  }
  const solrConfig = config.get('dbConfig.solr'),
    reqURL = 'http://' + solrConfig.host + ':' + solrConfig.port +
    '/solr/' + solrConfig.codeCollection + '/query',
    terms = _.map(codeQueries, (codeQuery) => {
      return '"' + _escapeSpecialCharacters(codeQuery) + '"';
    });
  const _text_ = terms.join(' && '),
    reqObj = {
      url: reqURL,
      qs: {
        q: '_text_:' + _text_,
        wt: 'json',
        rows: 1000000000,
        fl: 'id'
      }
    };

  const results = request.getAsync(reqObj)
    .get(1)
    .then((body) => {
      const docs = JSON.parse(body)
        .response.docs;
      return _.pluck(docs, 'id');
    })
    .catch(clientError, (e) => {
      log.error(e);
    });
  return Promise.resolve(results);
};

/**
 * Escape a string that uses any of Solr's special characters.
 * + - && || ! ( ) { } [ ] ^ " ~ * ? : /
 * @param str a String that may use any of the meta-characters
 * @returns {String} The escaped string with a single backslash proceeding the
 * special character.
 * @private
 */
function _escapeSpecialCharacters(str) {
  let escaped = str.replace(/([\+\-!\(\)\{}\[\]\^"~\*\?:\/])/g, '\\$1');
  escaped = escaped.replace('&&', '\\&&');
  escaped = escaped.replace('||', '\\||');
  return escaped;
}

@@ -1771,23 +1771,14 @@
 %0A%0A  
-const results =
+return
  req
@@ -1868,25 +1868,16 @@
 se(body)
-%0A        
 .respons
@@ -1882,30 +1882,39 @@
 nse.docs
-;
+,
 %0A      
-return
+  solrResults =
  _.pluck
@@ -1929,110 +1929,416 @@
 id')
-;%0A    %7D)%0A    .catch(clientError, (e) =%3E %7B%0A      log.error(e);%0A    %7D);%0A  return Promise.resolve(results
+,%0A        i = _.intersection(solrResults, options.scope);%0A      return Promise.resolve(i);%0A    %7D)%0A    .catch(clientError, (e) =%3E %7B%0A      log.error('Solr client error has occurred when submitting code query %25o',%0A        query, e);%0A      return Promise.reject(e);%0A    %7D)%0A    .catch((e) =%3E %7B%0A      log.error('Error in find by code when submitting code query %25o', query, e);%0A      return Promise.reject(e);%0A    %7D
 );%0A%7D

refactor and change log msgs