/*jslint node: true */
'use strict';

var mongoose = require('mongoose');
var util = require('../util');

function validateResponses (val) {
  return val !== undefined;
}

var responseSchema = new mongoose.Schema({
  __v: { type: Number, select: false },
  properties: {
    survey: String,
    humanReadableName: String,
    object_id: String,
    entries: [ {
      source: {
        type: { type: String },
        collector: String,
        started: Date,
        finished: Date
      },
      created: Date,
      files: [String],
      responses: {
        type: Object,
        validate: validateResponses
      }
    } ],
    centroid: [],
    indexedGeometry: {
      type: {
        type: { type: String },
        coordinates: []
      },
      select: false
    }
  },
  geometry: {
    type: { type: String },
    coordinates: []
  }
}, {
  autoIndex: false
});

// Indexes

// Ensure we have a geo index on the centroid field.
// We always restrict based on survey ID, so we use a compound index.
responseSchema.index({ survey: 1, 'properties.indexedGeometry': '2dsphere', created: 1 });

// Index the survey ID + creation date, which we use to sort
responseSchema.index({ survey: 1, created: 1 });

// Index the collector name
responseSchema.index({ survey: 1, 'source.collector': 1, created: 1 });

// Index the object ID
responseSchema.index({ survey: 1, object_id: 1 });

responseSchema.set('toObject', {
  transform: function (doc, ret, options) {
    return {
      type: 'Feature',
      id: ret._id,
      properties: ret.properties,
      geometry: ret.geometry
    };
  }
});


responseSchema.pre('save', function parseCentroid(next) {
  // check if there is a centroid. if yes, make sure the values are floats
  // TODO: abstract into a testable function.
  if (this.geo_info !== undefined) {
    var centroid = this.geo_info.centroid;
    if (centroid !== undefined) {
      centroid[0] = parseFloat(centroid[0]);
      centroid[1] = parseFloat(centroid[1]);
    }
  }
  next();
});


function simplify(ring) {
  // FIXME: Simplify the ring
  return ring;
}

function collectRingPoints(memo, ring) {
  simplify(ring).forEach(function (point) {
    memo.push(point);
  });
}

function collectPolygonPoints(memo, polygon) {
  polygon.forEach(function (ring) {
    collectRingPoints(memo, ring);
  });
}

function collectMultiPolygonPoints(memo, multiPolygon) {
  multiPolygon.forEach(function (polygon) {
    collectPolygonPoints(memo, polygon);
  });
}

// Collect all of the coordinates into one array, so we can index them.
responseSchema.pre('save', function collectPoints(next) {
  if (this.geometry !== undefined) {
    if (this.geometry.type === 'MultiPolygon') {
      this.geo_info.points = [];
      collectMultiPolygonPoints(this.geo_info.points, this.geo_info.geometry.coordinates);
    } else if (this.geometry.type === 'Polygon') {
      this.geo_info.points = [];
      collectPolygonPoints(this.geo_info.points, this.geo_info.geometry.coordinates);
    } else if (this.geometry.type === 'Point') {
      this.geo_info.points = this.geo_info.geometry.coordinates;
    }
  }
  next();
});

// Set the creation date.
responseSchema.pre('save', function setCreated(next) {
  if (this.created === undefined) {
    this.created = new Date();
  }
  next();
});

// Allow either parcel_id or object_id.
// Eventually we'll deprecate parcel_id.
responseSchema.pre('save', function setObjectId(next) {
  if (this.parcel_id !== undefined && this.object_id === undefined) {
    this.object_id = this.parcel_id;
  } else if (this.object_id !== undefined && this.parcel_id === undefined) {
    this.parcel_id = this.object_id;
  }
  next();
});

responseSchema.statics.getBounds = function getBounds(survey, done) {
  var bbox = [[-180, -89], [180, 89]];
  this.aggregate([
    {
      $match: { survey: survey }
    },
    {
      $project: {
        _id: '$_id',
        point: '$geo_info.centroid'
      }
    },
    {
      $unwind: '$point'
    },
    {
      $group: {
        _id: '$_id',
        x: { $first: '$point' },
        y: { $last: '$point' }
      }
    },
    {
      $group: {
        _id: 'bbox',
        minx: { $min: '$x' },
        miny: { $min: '$y' },
        maxx: { $max: '$x' },
        maxy: { $max: '$y' }
      }
    }
  ], function (error, response) {
    if (error) { return done(error); }

    if (response.length === 0) {
      return done(null, null);
    }

    var data = response[0];
    var bbox = [[ data.minx, data.miny ], [ data.maxx, data.maxy ]];
    done(null, bbox);
  });
};

var Response = module.exports = mongoose.model('Response', responseSchema, 'responseCollection');

@@ -3209,24 +3209,35 @@
 %0A  if (this.
+properties.
 created === 
@@ -3258,16 +3258,27 @@
    this.
+properties.
 created 
@@ -3352,48 +3352,93 @@
 t_id
-.%0A// Eventually we'll deprecate parcel_i
+ in the input, but only store object_id%0A// in the database.%0A// parcel_id is deprecate
 d.%0Ar
@@ -3605,118 +3605,103 @@
 ;%0A  
-%7D else if (this.object_id !== undefined && this.parcel_id === undefined) %7B%0A    this.parcel_id = this.object
+  delete this.parcel_id;%0A    console.log('warning issue=deprecated feature=response_parcel
 _id
+')
 ;%0A  

Tweak some references to old fields