<commit_before>'use strict';

var ejs = require('elastic.js');
var _ = require('lodash');
var moment = require('moment');
var gjv = require('geojson-validation');
var err = require('../errors.js');

/**
 * @apiDefine search
 * @apiParam {string} [search] Supports Lucene search syntax for all available fields
 * in the landsat meta data. <br> If search is used, all other parameters are ignored.
**/
var legacyParams = function (params, q, limit) {
  var supported_query_re = new RegExp('^[0-9a-zA-Z#\*\.\_\:\(\)\"\\[\\]\{\}\\-\\+\>\<\= ]+$');

  if (params.search) {
    if (!supported_query_re.test(params.search)) {
      err.searchNotSupportedError(params.search);
    }

    q.query(ejs.QueryStringQuery(params.search));
  } else if (params.count) {
    q.facet(ejs.TermsFacet('count').fields([params.count]).size(limit));
  }

  return q;
};

/**
 * @apiDefine contains
 * @apiParam {string} [contains] Evaluates whether the given point is within the
 * bounding box of a landsat image.
 *
 * Accepts `latitude` and `longitude`. They have to be separated by a `,`
 * with no spaces in between. Example: `contains=23,21`
**/
var contains = function (params, query) {
  var correct_query = new RegExp('^[0-9\.\,\-]+$');
  if (correct_query.test(params)) {
    var coordinates = params.split(',').map(parseFloat);

    query.boundingBox = {
       $geoIntersects: {
          $geometry: {
             type: 'Point',
             coordinates: coordinates
          }
       }
    };

    return query;
  } else {
    err.incorrectCoordinatesError(params);
  }
};

/**
 * @apiDefine intersects
 * @apiParam {string/geojson} [intersects] Evaluates whether the give geojson is intersects
 * with any landsat images.
 *
 * Accepts valid geojson.
**/
var intersects = function (params, query) {
  // if we receive an object, assume it's GeoJSON, if not, try and parse
  var geojson;
  if (typeof (params) === 'object') {
    geojson = params;
  } else {
    try {
      geojson = JSON.parse(params);
    } catch (e) {
      err.invalidGeoJsonError();
    }
  }

  if (gjv.valid(geojson)) {
    var geometry;
    if (geojson.type === 'FeatureCollection') {
      geometry = geojson.features[0].geometry;
    }

    if (geojson.type === 'Feature') {
      geometry = geojson.geometry;
    }

    query.boundingBox = { $geoIntersects: { $geometry: geometry } };
    return query;
  } else {
    err.invalidGeoJsonError();
  }
};

/**
 * @apiDefine rangeFields
 * @apiParam {string} [date_from] The lower limit for `acquisitionDate` field.
 * Returns all records with `acquisitionDate` after this date. <br>
 * Accepted format: `YYYY-MM-DD`.
 *
 * @apiParam {string} [date_to] The upper limit for `acquisitionDate` field.
 * Returns all records with `acquisitionDate` before this date. <br>
 * Accepted format: `YYYY-MM-DD`.
 *
 * @apiParam {string} [scene_start_time_from] The lower limit for `sceneStartTime` field.
 * Returns all records with `sceneStartTime` after this date. <br>
 * Accepted format: `YYYY-MM-DD`.
 *
 * @apiParam {string} [scene_start_time_to] The upper limit for `sceneStartTime` field.
 * Returns all records with `sceneStartTime` before this date. <br>
 * Accepted format: `YYYY-MM-DD` or `YYYY-MM-DD HH:mm:ss.ZZZ`.
 *
 * @apiParam {number} [cloud_from] The lower limit for `cloudCoverFull` field.
 * Returns all records with `cloudCoverFull` greater than this value.
 *
 * @apiParam {number} [cloud_to] The upper limit for `cloudCoverFull` field.
 * Returns all records with `cloudCoverFull` smaller than this value.
 *
 * @apiParam {number} [sun_azimuth_from] The lower limit for `sunAzimuth` field.
 * Returns all records with `sunAzimuth` greater than this value.
 *
 * @apiParam {number} [sun_azimuth_to] The upper limit for `sunAzimuth` field.
 * Returns all records with `sunAzimuth` smaller than this value.
 *
 * @apiParam {number} [sun_elevation_from] The lower limit for `sunElevation` field.
 * Returns all records with `sunElevation` greater than this value.
 *
 * @apiParam {number} [sun_elevation_to] The upper limit for `sunElevation` field.
 * Returns all records with `sunElevation` smaller than this value.
**/

var rangeQuery = function (from, to, field, query) {
  if (field in ['acquisitionDate', 'sceneStartTime', 'sceneStopTime']) {
    if (to) to = moment(to).format();
    if (from) from = moment(from).format();
  }

  if (from && to) {
    query[field] = {$gte: from, $lte: to};
    return query;
  }

  if (from) {
    query[field] = {$gte: from};
    return query;
  }

  if (to) {
    query[field] = {$lte: to};
    return query;
  }
};

/**
 * @apiDefine termFields
 * @apiParam {string} [scene_id] Performs exact search on `sceneID` field.
 * @apiParam {number} [row] Performs exact search on `row` field.
 * @apiParam {number} [path] Performs exact search on `path` field.
 * @apiParam {string} [sensor] Performs exact search on `sensor` field.
 * @apiParam {string} [receiving_station] Performs exact search on `receivingStation` field.
 * @apiParam {string="day","night"} [day_or_night=night] Performs exact search on `dayOrNight` field.
 *
**/
var termQuery = function (param, field, query) {
  query[field] = param;
  return query;
};

module.exports = function (params, query, limit) {

  var rangeFields = [
    {
      from: 'date_from',
      to: 'date_to',
      field: 'acquisitionDate'
    },
    {
      from: 'scene_start_time_from',
      to: 'scene_start_time_to',
      field: 'sceneStartTime'
    },
    {
      from: 'scene_stop_time_from',
      to: 'scene_stop_time_to',
      field: 'sceneStopTime'
    },
    {
      from: 'cloud_from',
      to: 'cloud_to',
      field: 'cloudCoverFull'
    },
    {
      from: 'sun_azimuth_from',
      to: 'sun_azimuth_to',
      field: 'sunAzimuth'
    },<commit_msg>add lucene support<commit_after>'use strict';

var ejs = require('elastic.js');
var _ = require('lodash');
var moment = require('moment');
var compile = require('monquery');
var gjv = require('geojson-validation');
var err = require('../errors.js');

/**
 * @apiDefine search
 * @apiParam {string} [search] Supports Lucene search syntax for all available fields
 * in the landsat meta data. <br> If search is used, all other parameters are ignored.
**/
var legacyParams = function (params) {
  var supported_query_re = new RegExp('^[0-9a-zA-Z#\*\.\_\:\(\)\"\\[\\]\{\}\\-\\+\>\<\= ]+$');

  if (!supported_query_re.test(params.search)) {
    err.searchNotSupportedError(params.search);
  }

  return compile(params.search);
};

/**
 * @apiDefine contains
 * @apiParam {string} [contains] Evaluates whether the given point is within the
 * bounding box of a landsat image.
 *
 * Accepts `latitude` and `longitude`. They have to be separated by a `,`
 * with no spaces in between. Example: `contains=23,21`
**/
var contains = function (params, query) {
  var correct_query = new RegExp('^[0-9\.\,\-]+$');
  if (correct_query.test(params)) {
    var coordinates = params.split(',').map(parseFloat);

    query.boundingBox = {
       $geoIntersects: {
          $geometry: {
             type: 'Point',
             coordinates: coordinates
          }
       }
    };

    return query;
  } else {
    err.incorrectCoordinatesError(params);
  }
};

/**
 * @apiDefine intersects
 * @apiParam {string/geojson} [intersects] Evaluates whether the give geojson is intersects
 * with any landsat images.
 *
 * Accepts valid geojson.
**/
var intersects = function (params, query) {
  // if we receive an object, assume it's GeoJSON, if not, try and parse
  var geojson;
  if (typeof (params) === 'object') {
    geojson = params;
  } else {
    try {
      geojson = JSON.parse(params);
    } catch (e) {
      err.invalidGeoJsonError();
    }
  }

  if (gjv.valid(geojson)) {
    var geometry;
    if (geojson.type === 'FeatureCollection') {
      geometry = geojson.features[0].geometry;
    }

    if (geojson.type === 'Feature') {
      geometry = geojson.geometry;
    }

    query.boundingBox = { $geoIntersects: { $geometry: geometry } };
    return query;
  } else {
    err.invalidGeoJsonError();
  }
};

/**
 * @apiDefine rangeFields
 * @apiParam {string} [date_from] The lower limit for `acquisitionDate` field.
 * Returns all records with `acquisitionDate` after this date. <br>
 * Accepted format: `YYYY-MM-DD`.
 *
 * @apiParam {string} [date_to] The upper limit for `acquisitionDate` field.
 * Returns all records with `acquisitionDate` before this date. <br>
 * Accepted format: `YYYY-MM-DD`.
 *
 * @apiParam {string} [scene_start_time_from] The lower limit for `sceneStartTime` field.
 * Returns all records with `sceneStartTime` after this date. <br>
 * Accepted format: `YYYY-MM-DD`.
 *
 * @apiParam {string} [scene_start_time_to] The upper limit for `sceneStartTime` field.
 * Returns all records with `sceneStartTime` before this date. <br>
 * Accepted format: `YYYY-MM-DD` or `YYYY-MM-DD HH:mm:ss.ZZZ`.
 *
 * @apiParam {number} [cloud_from] The lower limit for `cloudCoverFull` field.
 * Returns all records with `cloudCoverFull` greater than this value.
 *
 * @apiParam {number} [cloud_to] The upper limit for `cloudCoverFull` field.
 * Returns all records with `cloudCoverFull` smaller than this value.
 *
 * @apiParam {number} [sun_azimuth_from] The lower limit for `sunAzimuth` field.
 * Returns all records with `sunAzimuth` greater than this value.
 *
 * @apiParam {number} [sun_azimuth_to] The upper limit for `sunAzimuth` field.
 * Returns all records with `sunAzimuth` smaller than this value.
 *
 * @apiParam {number} [sun_elevation_from] The lower limit for `sunElevation` field.
 * Returns all records with `sunElevation` greater than this value.
 *
 * @apiParam {number} [sun_elevation_to] The upper limit for `sunElevation` field.
 * Returns all records with `sunElevation` smaller than this value.
**/

var rangeQuery = function (from, to, field, query) {
  if (field in ['acquisitionDate', 'sceneStartTime', 'sceneStopTime']) {
    if (to) to = moment(to).format();
    if (from) from = moment(from).format();
  }

  if (from && to) {
    query[field] = {$gte: from, $lte: to};
    return query;
  }

  if (from) {
    query[field] = {$gte: from};
    return query;
  }

  if (to) {
    query[field] = {$lte: to};
    return query;
  }
};

/**
 * @apiDefine termFields
 * @apiParam {string} [scene_id] Performs exact search on `sceneID` field.
 * @apiParam {number} [row] Performs exact search on `row` field.
 * @apiParam {number} [path] Performs exact search on `path` field.
 * @apiParam {string} [sensor] Performs exact search on `sensor` field.
 * @apiParam {string} [receiving_station] Performs exact search on `receivingStation` field.
 * @apiParam {string="day","night"} [day_or_night=night] Performs exact search on `dayOrNight` field.
 *
**/
var termQuery = function (param, field, query) {
  query[field] = param;
  return query;
};

module.exports = function (params, query, limit) {
  // if search parameters included ignore other parameters and do legacy search
  if (params.search) {
    return legacyParams(params);
  }

  var rangeFields = [
    {
      from: 'date_from',
      to: 'date_to',
      field: 'acquisitionDate'
    },
    {
      from: 'scene_start_time_from',
      to: 'scene_start_time_to',
      field: 'sceneStartTime'
    },
    {
      from: 'scene_stop_time_from',
      to: 'scene_stop_time_to',
      field: 'sceneStopTime'
    },
    {
      from: 'cloud_from',
      to: 'cloud_to',
      field: 'cloudCoverFull'
    },
    {
      from: 'sun_azimuth_from',
      to: 'sun_azimuth_to',
      field: 'sunAzimuth'
    },
{'fraction_non_alphanumeric': 0.14149883308842598, 'fraction_numerical': 0.0015558820987120754, 'mean_word_length': 3.4210928544134505, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '949470', 'n_tokens_mistral': 3871, 'n_tokens_neox': 3739, 'n_words': 1105}