{"size": 3440, "ext": "js", "max_stars_repo_path": "lib/marco.js", "max_stars_repo_name": "rodowi/marco", "max_stars_repo_stars_event_min_datetime": "2016-04-25T17:35:31.000Z", "max_stars_repo_stars_event_max_datetime": "2016-06-14T07:48:21.000Z", "max_issues_repo_path": "lib/marco.js", "max_issues_repo_name": "rodowi/marco", "max_issues_repo_issues_event_min_datetime": "2016-04-26T01:58:53.000Z", "max_issues_repo_issues_event_max_datetime": "2016-05-30T18:04:40.000Z", "max_forks_repo_path": "lib/marco.js", "max_forks_repo_name": "defvol/marco", "max_forks_repo_forks_event_min_datetime": "2016-09-18T06:28:44.000Z", "max_forks_repo_forks_event_max_datetime": "2016-09-18T06:28:44.000Z"}
{"max_stars_count": 9, "max_issues_count": 4, "max_forks_count": 1, "avg_line_length": 25.1094890511, "max_line_length": 81, "alphanum_fraction": 0.6389534884}
const path = require('path');
const readline = require('readline');
const fs = require('fs');
const through = require('through2');
const concat = require('concat-stream');

const aliases = {
  'ciudad de mexico': 'distrito federal',
  'ciudad de méxico': 'distrito federal',
  'coahuila': 'coahuila de zaragoza',
  'michoacan': 'michoacán de ocampo',
  'michoacán': 'michoacán de ocampo',
  'queretaro': 'querétaro',
  'veracruz': 'veracruz de ignacio de la llave'
}

function lineToJSON(lineString) {
  try {
    var line = lineString.trim();
    if (line[line.length - 1] == ',')
      return JSON.parse(line.slice(0, line.length - 1));
    else
      return JSON.parse(line);
  } catch (err) {
    return {};
  }
}

function matchInReadStream(matchFun, stream, cb) {
  var match = null;

  stream.on('line', (line) => {
    var feature = lineToJSON(line);
    if (matchFun(feature)) {
      match = feature;
      stream.close();
    }
  });

  stream.on('close', () => {
    cb(null, match);
  });
}

function findState(opts, cb) {
  const { query } = opts;
  const source = path.join(opts.source || 'data/states.json');

  var db = readline.createInterface({
    input: fs.createReadStream(source)
  });

  var match = (obj = {}) => {
    if (obj.properties && obj.properties.NOM_ENT) {
      const { NOM_ENT } = obj.properties;
      const q = String(query).toLowerCase();
      return NOM_ENT.toLowerCase() === q || NOM_ENT.toLowerCase() === aliases[q];
    }
  }

  matchInReadStream(match, db, function (err, data) {
    cb(err, data);
  });
}

function findMunicipality(opts, cb) {
  const { query } = opts;
  const source = path.join(opts.source || 'data/municipalities.json');

  var db = readline.createInterface({
    input: fs.createReadStream(source)
  });

  var match = (obj) => (obj.properties && obj.properties.NOM_MUN == query);

  matchInReadStream(match, db, function (err, data) {
    cb(err, data);
  });
}

// through2 streamers

function toStatePolygon(opts = {}) {
  return through((buf, _, next) => {
    var line = buf.toString();
    var name = line.split(',')[0];

    var source = opts.source;
    findState({ query: name, source }, function (err, data) {
      if (!err && data) next(null, JSON.stringify(data) + '\n');
      else next();
    });
  });
}

function toMunicipalityPolygon(opts = {}) {
  return through((buf, _, next) => {
    var line = buf.toString();
    var name = line.split(',')[0];

    var source = opts.source;
    findMunicipality({ query: name, source }, function (err, data) {
      if (!err && data) next(null, JSON.stringify(data) + '\n');
      else next();
    });
  });
}

/**
 * Returns a stringified GeoJSON FeatureCollection
 * @param {features} a string buffer delimited by line-breaks
 */
function toFeatureCollection(features) {
  // Note: trim trailing line-break
  var f = features.trim().split('\n').join(',\n');
  return '{"type":"FeatureCollection","features":[\n' + f + '\n]}';
}

// concat-streamers

function concatFeatureCollection() {
  return concat(function (body) {
    console.log(toFeatureCollection(body.toString()));
  });
}

module.exports = {
  concatFeatureCollection: concatFeatureCollection,
  findMunicipality: findMunicipality,
  findState: findState,
  lineToJSON: lineToJSON,
  matchInReadStream: matchInReadStream,
  toFeatureCollection: toFeatureCollection,
  toStatePolygon: toStatePolygon,
  toMunicipalityPolygon: toMunicipalityPolygon
}
