import fs from 'fs'
import glob from 'glob'
import yazl from 'yazl'

/**
 * @class
 */
export default class Action {
  /**
   * @param {String} name
   */
  constructor({ name }) {
    this.name = name;
  }

  /**
   * @return {Promise}
   */
  createZipFile() {
    return new Promise((resolve, reject) => {
      const zipfile = new yazl.ZipFile();
      glob.sync(`${this.getDirectoryPath()}/dist/**/*.js`).forEach((path) => {
        zipfile.addFile(
          path,
          path.substr(`${this.getDirectoryPath()}/dist/`.length)
        );
      });
      zipfile.outputStream.pipe(
        fs.createWriteStream(`${this.getDirectoryPath()}/dist.zip`)
      ).on('close', () => {
        console.log(`Created ${this.getDirectoryPath()}/dist.zip`);
        resolve();
      });
      zipfile.end();
    });
  }

  /**
   * @return {String}
   */
  getDirectoryPath() {
    return `./actions/${this.name}`;
  }

  /**
   * @return {Function}
   */
  getHandler() {
    const handlerScriptPath = `${process.cwd()}/${this.getDirectoryPath()}/dist`;
    delete(require.cache[handlerScriptPath]);
    return require(handlerScriptPath).handler;
  }

  /**
   * @return {String}
   */
  getHandlerId() {
    return 'index.handler';
  }

  /**
   * @return {String}
   */
  getHttpMethod() {
    return this.getMetadata().fluct.httpMethod;
  }

  /**
   * @return {String}
   */
  getName() {
    return this.getMetadata().name;
  }

  /**
   * @return {Object}
   */
  getMetadata() {
    return JSON.parse(
      fs.readFileSync(`${this.getDirectoryPath()}/package.json`)
    );
  }

  /**
   * @return {String}
   */
  getPath() {
    return this.getMetadata().fluct.path;
  }

  /**
   * @return {String}
   */
  getRegion() {
    return 'us-east-1';
  }

  /**
   * @return {Object}
   */
  getResponseModels() {
    if (this.getMetadata().fluct.contentType == 'application/json') {
      return {}
    } else {
      return { 'text/html': 'Empty' }
    }
  }

  /**
   * @return {Object}
   */
  getResponseTemplates() {
    if (this.getMetadata().fluct.contentType == 'application/json') {
      return {}
    } else {
      return { 'text/html': "$input.path('$')" }
    }
  }

  /**
   * @return {Integer}
   */
  getTimeout() {
    return 60;
  }

  /**
   * @return {String}
   */
  getUri() {
    return `arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/${this.getMetadata().fluct.arn}/invocations`;
  }

  /**
   * @param {http.IncomingMessage} request
   * @param {http.ServerResponse} response
   */
  run(request, response) {
    this.getHandler()(
      {},
      {
        succeed: (value) => {
          response.send(value);
        }
      }
    );
  }

  /**
   * @param {String} arn
   */
  writeArn(arn) {
    const metadata = this.getMetadata();
    metadata.fluct.arn = arn;
    fs.writeSync(
      fs.openSync(`${this.getDirectoryPath()}/package.json`, 'w'),
      JSON.stringify(metadata, null, 2)
    );
  }
}

@@ -298,24 +298,74 @@
 eject) =%3E %7B%0A
+      const actionPath = this.getDirectoryPath();%0A
       const 
@@ -413,39 +413,26 @@
 sync(%60$%7B
-this.getDirectory
+action
 Path
-()
 %7D/dist/*
@@ -434,19 +434,16 @@
 ist/**/*
-.js
 %60).forEa
@@ -453,24 +453,75 @@
 (path) =%3E %7B%0A
+        if (!fs.lstatSync(path).isDirectory()) %7B%0A  
         zipf
@@ -547,14 +547,18 @@
     
+  
 path,%0A
+  
     
@@ -582,37 +582,271 @@
 (%60$%7B
-this.getDirectoryPath()%7D/dist
+actionPath%7D/dist/%60.length)%0A          );%0A        %7D%0A      %7D);%0A      glob.sync(%60$%7BactionPath%7D/node_modules/**/*%60).forEach((path) =%3E %7B%0A        if (!fs.lstatSync(path).isDirectory()) %7B%0A          zipfile.addFile(%0A            path,%0A            path.substr(%60$%7BactionPath%7D
 /%60.l
@@ -856,26 +856,38 @@
 th)%0A        
-);
+  );%0A        %7D
 %0A      %7D);%0A 
@@ -950,39 +950,26 @@
 ream(%60$%7B
-this.getDirectory
+action
 Path
-()
 %7D/dist.z
@@ -1032,39 +1032,26 @@
 eated $%7B
-this.getDirectory
+action
 Path
-()
 %7D/dist.z

Include node_modules into Lambda function