import SparkPlugin from '@ciscospark/spark-core';
import JSZip from 'jszip';
import saveAs from 'file-saver';
import MimeBuilder from 'emailjs-mime-builder';
import Blob from 'blob';

/**
 * @class ReportGenerator is used to compile, zip, and save an eDiscovery report to disk.
 *
 * Warning: This file is browser specific. It cannot function in a NodeJS server environment.
 */
const ReportGenerator = SparkPlugin.extend({
  namespace: 'EDiscovery',

  props: {
    reportId: 'string',
    zip: 'object',
    folder: 'object',
    spaces: 'object',
    size: {type: 'number', default: 0},
    maxSize: {type: 'number', default: 1000000}
  },

  /**
   * Create a new report-generator specific to one report.
   *
   * @param {Object} attrs
   * @param {Object} attrs.reportId - The uuid of the report.
   * @param {Object} options - Additional options passed up to the parent.
   * @returns {Object} A report generator object.
   */
  initialize(attrs, options) {
    Reflect.apply(SparkPlugin.prototype.initialize, this, [attrs, options]);

    if (!attrs || !attrs.reportId) {
      throw Error('Missing Required Argument reportId');
    }
  },

  /**
   * Initialize the zip file settings.
   * @private
   * @returns {Void}
   */
  _initZip() {
    this.zip = new JSZip();
    this.folder = this.zip.folder(`${this.reportId}`);
    this.spaces = {};
    this.size = 0;
  },

  /**
   * Map an activity to an MIME rfc822 formated string that can be saved as an eml file.
   * @param {Object} activity - An activity object
   * @returns {String} A string that represents the data stored in an eml file.
   */
  map(activity) {
    if (!activity) {
      throw Error('Invalid activity');
    }

    const mime = new MimeBuilder('multipart/mixed')
      .setHeader('From', activity.actorDisplayName)
      .setHeader('Subject', activity.activityId)
      .setHeader('Date', activity.timestamp);

    let content = activity.objectDisplayName;
    if (activity.verb !== 'post') {
      content = activity.verb;
      // Include the target of the event. e.g. Add Person
      if (activity.objectId) {
        content += ` ${activity.objectId}`;
      }
    }

    mime.createChild('text/plain')
      .setContent(content);

    if (activity.verb === 'share' && activity.files) {
      for (let i = 0; i < activity.files.length; i += 1) {
        const file = activity.files[i];
        if (file.name && file.content) {
          mime.createChild(file.mimeType, {filename: file.name})
            .setContent(file.content)
            .setHeader('Content-Disposition', 'attachment');
        }
      }
    }

    return mime.build();
  },

  /**
   * Add an activity to the report.
   * @param {Object} activity - An activity to be part of the report
   * @returns {Void}
   */
  add(activity) {
    if (!this.zip) {
      this._initZip();
    }

    // If there is no target id use the report id folder
    let space = this.folder;
    if (activity.targetId) {
      if (!(activity.targetId in this.spaces)) {
        // Create sub-folder for space id
        this.spaces[activity.targetId] = this.folder.folder(`${activity.targetId}`);
      }

      space = this.spaces[activity.targetId];
    }

    const data = this.map(activity);
    // Create a blob 'reference' to data in order to count its byte size
    const blob = new Blob([data], {type: 'text/plain'});
    this.size += blob.size;
    space.file(`${activity.activityId}.eml`, blob);

    if (this.size > this.maxSize) {
      this.logger.info(`Triggering a download for zip size: ${this.size}`);
      this.generate();
    }
  },

  /**
   * Once all the activities have been added create a report and save it to disk.
   * @returns {Promise} A promise on the generated report
   */
  generate() {
    if (!this.zip) {
      return Promise.resolve();
    }

    const generatePromise = this.zip.generateAsync({type: 'blob'})
      .then((content) => {
        // Download to the user's browser
        saveAs(content, `${this.reportId}.zip`);
      });

    // Reset the zip
    this._initZip();

    return generatePromise;
  }
});

export default ReportGenerator;

@@ -628,14 +628,35 @@
 : 10
-00000%7D
+4857600%7D // 100 Mb max size
 %0A  %7D
@@ -3782,32 +3782,48 @@
    if (!this.zip
+ %7C%7C !this.spaces
 ) %7B%0A      return

bump maxsize to 100 mb