const _ = require('lodash');

const Shape = require('../../models/shape');
const Trip = require('../../models/trip');

function shapesToGeoJSON(shapes, routeId) {
  return {
    type: 'FeatureCollection',
    features: shapes.map(shape => ({
      type: 'Feature',
      geometry: {
        type: 'LineString',
        coordinates: shape.map(point => point.loc)
      },
      properties: {
        route_id: routeId,
        shape_id: shape && shape.length ? shape[0].shape_id : null,
        agency_key: shape && shape.length ? shape[0].agency_key : null
      }
    }))
  };
}

/*
 * Returns an array of shapes for the `agencyKey`, `routeId` and
 * `directionId` specified
 */
exports.getShapesByRoute = (agencyKey, routeId, directionId, serviceIds, cb) => {
  if (_.isFunction(directionId)) {
    cb = directionId;
    directionId = undefined;
    serviceIds = undefined;
  }

  if (_.isFunction(serviceIds)) {
    cb = serviceIds;
    serviceIds = undefined;
  }

  return exports.getShapeIdsByRoute(agencyKey, routeId, directionId, serviceIds).then(results => {
    // Remove empty strings
    const shapeIds = _.compact(results);

    return exports.getShapesByShapeId(agencyKey, shapeIds);
  }).then(shapes => {
    if (cb) {
      cb(null, shapes);
    }

    return shapes;
  })
  .catch(cb);
};

/*
 * Returns geoJSON of the shapes for the `agencyKey`, `routeId` and
 * `directionId` specified
 */
exports.getShapesByRouteAsGeoJSON = (agencyKey, routeId, directionId, serviceIds, cb) => {
  if (_.isFunction(directionId)) {
    cb = directionId;
    directionId = undefined;
    serviceIds = undefined;
  }

  if (_.isFunction(serviceIds)) {
    cb = serviceIds;
    serviceIds = undefined;
  }

  return exports.getShapesByRoute(agencyKey, routeId, directionId, serviceIds)
  .then(shapes => {
    return shapesToGeoJSON(shapes, routeId);
  })
  .then(geojson => {
    if (cb) {
      cb(null, geojson);
    }

    return geojson;
  })
  .catch(cb);
};

/*
 * Returns an array of shape_ids for the `agencyKey`, `routeId` and
 * `directionId` specified
 */
exports.getShapeIdsByRoute = (agencyKey, routeId, directionId, serviceIds) => {
  const query = {
    agency_key: agencyKey,
    route_id: routeId
  };

  if (directionId !== undefined) {
    query.direction_id = directionId;
  } // else match all directionIds

  if (serviceIds && serviceIds.length > 0) {
    query.service_id = {
      $in: serviceIds
    };
  }

  return Trip
    .find(query)
    .distinct('shape_id')
    .exec();
};

/*
 * Returns an array of shapes for the `shape_ids` specified
 */
exports.getShapesByShapeId = (agencyKey, shapeIds) => {
  const shapes = [];

  return Promise.all(shapeIds.map(shapeId => {
    return Shape.find({
      agency_key: agencyKey,
      shape_id: shapeId
    })
    .sort({shape_pt_sequence: 1})
    .then(shapePts => {
      if (!shapePts || shapePts.length === 0) {
        throw (new Error(`No shapes with shape_id ${shapeId}.`));
      }

      shapes.push(shapePts);
    });
  })).then(() => {
    return shapes;
  });
};

@@ -23,16 +23,61 @@
 ash');%0A%0A
+const Route = require('../../models/route');%0A
 const Sh
@@ -181,32 +181,43 @@
 oGeoJSON(shapes,
+ agencyKey,
  routeId) %7B%0A  re
@@ -221,18 +221,120 @@
  return 
-%7B%0A
+Route.findOne(%7B%0A    agency_key: agencyKey,%0A    route_id: routeId%0A  %7D)%0A  .then(route =%3E %7B%0A    return %7B%0A  
     type
@@ -356,16 +356,18 @@
 ction',%0A
+  
     feat
@@ -393,32 +393,34 @@
 ape =%3E (%7B%0A      
+  
 type: 'Feature',
@@ -426,16 +426,18 @@
 ,%0A      
+  
 geometry
@@ -444,24 +444,26 @@
 : %7B%0A        
+ 
+ 
 type: 'LineS
@@ -470,16 +470,18 @@
 tring',%0A
+  
         
@@ -523,16 +523,18 @@
 nt.loc)%0A
+  
       %7D,
@@ -540,16 +540,18 @@
 ,%0A      
+  
 properti
@@ -557,196 +557,36 @@
 ies:
- %7B%0A        route_id:
  route
-Id,
 %0A      
-  shape_id: shape && shape.length ? shape%5B0%5D.shape_id : null,%0A        agency_key: shape && shape.length ? shape%5B0%5D.agency_key : null%0A  
+%7D))%0A
     %7D
+;
 %0A
-  
   %7D)
-)%0A  %7D
 ;%0A%7D%0A
@@ -1845,16 +1845,27 @@
 (shapes,
+ agencyKey,
  routeId

add route properties to shape geoJSON