/*
cacophony-api: The Cacophony Project API server
Copyright (C) 2018  The Cacophony Project

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

var log = require('../../logging');
var responseUtil = require('./responseUtil');
const uuidv4            = require('uuid/v4');
const multiparty        = require('multiparty');
const config            = require('../../config');
const modelsUtil        = require('../../models/util/util');


function multipartUpload(buildRecord){
  return (request, response) => {
    var key = uuidv4();
    var data;
    var filename;
    var upload;

    // Note regarding multiparty: there are no guarantees about the
    // order that the field and part handlers will be called. You need
    // to formulate the response to the client in the close handler.
    var form = new multiparty.Form();

    // Handle the "data" field.
    form.on('field', (name, value) => {
      if (name != 'data') {
        return;
      }

      try {
        data = JSON.parse(value);
      } catch (err) {
        // This leaves `data` unset so that the close handler (below)
        // will fail the upload.
        log.error("Invalid 'data' field: ", err);
      }
    });

    // Handle the "file" part.
    form.on('part', (part) => {
      if (part.name != 'file') {
        part.resume();
        return;
      }
      filename = part.filename;

      upload = modelsUtil.openS3().upload({
        Bucket: config.s3.bucket,
        Key: key,
        Body: part,
      }).promise()
        .catch((err) => {
          return err;
        });
      log.debug('Started streaming upload to bucket...');
    });

    // Handle any errors. If this is called, the close handler
    // shouldn't be.
    form.on('error', (err) => {
      responseUtil.serverError(response, err);
    });

    // This gets called once all fields and parts have been read.
    form.on('close', async () => {
      if (!data) {
        log.error("Upload missing 'data' field.");
        responseUtil.invalidDatapointUpload(response);
        return;
      }
      if (!upload) {
        log.error("Upload was never started.");
        responseUtil.invalidDatapointUpload(response);
        return;
      }

      var dbRecord;
      try {
        // Wait for the upload to complete.
        var uploadResult = await upload;
        if (uploadResult instanceof Error) {
          responseUtil.serverError(response, uploadResult);
          return;
        }
        log.info("Finished streaming upload to object store. Key:", key);

        data.filename = filename;

        // Store a record for the upload.
        dbRecord = buildRecord(request, data, key);
        await dbRecord.validate();
        await dbRecord.save();
      } catch (err) {
        responseUtil.serverError(response, err);
        return;
      }
      responseUtil.validRecordingUpload(response, dbRecord.id);
    });

    form.parse(request);
  };
}

exports.multipartUpload = multipartUpload;

@@ -728,86 +728,44 @@
 */%0A%0A
-var log = require('../../logging');%0Avar responseUtil = require('./responseUtil
+const moment       = require('moment
 ');%0A
@@ -779,29 +779,24 @@
 uidv4       
-     
 = require('u
@@ -824,21 +824,16 @@
 party   
-     
 = requir
@@ -859,19 +859,109 @@
 nst 
+log          = require('../../logging');%0Aconst responseUtil = require('./responseUtil');%0Aconst 
 config
-     
     
@@ -1009,21 +1009,16 @@
 sUtil   
-     
 = requir
@@ -1117,24 +1117,24 @@
 ponse) =%3E %7B%0A
-
     var key 
@@ -1134,16 +1134,49 @@
 ar key =
+ moment().format('YYYY/MM/DD/') +
  uuidv4(

Add date components in object storage path