text: const APP_ROOT = '../../'
  const _ = require('lodash')
  const util = require('util')
  const aws4 = require('aws4')
  const URL = require('url')
  const http = require('superagent-promise')(require('superagent'), Promise)
  const mode = process.env.TEST_MODE
  
  const respondFrom = async (httpRes) => {
    const contentType = _.get(httpRes, 'headers.content-type', 'application/json')
    const body = 
      contentType === 'application/json'
        ? httpRes.body
        : httpRes.text
  
    return { 
      statusCode: httpRes.status,
      body: body,
      headers: httpRes.headers
    }
  }
  
  const signHttpRequest = (url, httpReq) => {
    const urlData = URL.parse(url)
    const opts = {
      host: urlData.hostname, 
      path: urlData.pathname
    }
  
    aws4.sign(opts)
  
    httpReq
      .set('Host', opts.headers['Host'])
      .set('X-Amz-Date', opts.headers['X-Amz-Date'])
      .set('Authorization', opts.headers['Authorization'])
  
    if (opts.headers['X-Amz-Security-Token']) {
      httpReq.set('X-Amz-Security-Token', opts.headers['X-Amz-Security-Token'])
    }
  }
  
  const viaHttp = async (relPath, method, opts) => {
    const root = process.env.TEST_ROOT
    const url = `${root}/${relPath}`
    console.log(`invoking via HTTP ${method} ${url}`)
  
    try {
      const httpReq = http(method, url)
  
      const body = _.get(opts, "body")
      if (body) {      
        httpReq.send(body)
      }
  
      if (_.get(opts, "iam_auth", false) === true) {
        signHttpRequest(url, httpReq)
      }
  
      const authHeader = _.get(opts, "auth")
      if (authHeader) {
        httpReq.set('Authorization', authHeader)
      }
  
      const res = await httpReq
      return respondFrom(res)
    } catch (err) {
      if (err.status) {
        return {
          statusCode: err.status,
          headers: err.response.headers
        }
      } else {
        throw err
      }
    }
  }
  
  const toKinesisEvent = events => {
    const records = events.map(event => {
      const data = Buffer.from(JSON.stringify(event)).toString('base64')
      return {
        "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961",
        "eventVersion": "1.0",
        "kinesis": {
          "approximateArrivalTimestamp": 1428537600,
          "partitionKey": "partitionKey-3",
          "data": data,
          "kinesisSchemaVersion": "1.0",
          "sequenceNumber": "49545115243490985018280067714973144582180062593244200961"
        },
        "invokeIdentityArn": "arn:aws:iam::EXAMPLE",
        "eventName": "aws:kinesis:record",
        "eventSourceARN": "arn:aws:kinesis:EXAMPLE",
        "eventSource": "aws:kinesis",
        "awsRegion": "us-east-1"
      }
    })
  
    return {
      Records: records
    }
  }
  
  const viaHandler = async (event, functionName) => {
    const handler = util.promisify(require(`${APP_ROOT}/functions/${functionName}`).handler)
    console.log(`invoking via handler function ${functionName}`)
  
    const context = {}
    const response = await handler(event, context)
    const contentType = _.get(response, 'headers.content-type', 'application/json');
    if (_.get(response, 'body') && contentType === 'application/json') {
      response.body = JSON.parse(response.body);
    }
    return response
  }
  
  const we_invoke_search_restaurants = async (theme) => {
    const body = JSON.stringify({ theme })
  
    const res = 
      mode === 'handler'
        ? viaHandler({ body }, 'search-restaurants')
        : viaHttp('restaurants/search', 'POST', { body })
  
    return res
  }
  
  const we_invoke_place_order = async (restaurantName) => {
    const body = JSON.stringify({ restaurantName }) 
    return viaHandler({ body }, 'place-order')      
  }
  
  const we_invoke_notify_restaurant = async (...events) => {
    return viaHandler(toKinesisEvent(events), 'notify-restaurant')
  }
  
  const we_invoke_get_index = async () => {
    const res = 
      mode === 'handler' 
        ? await viaHandler({}, 'get-index')
        : await viaHttp('', 'GET')
  
    return res
  }
  
  const we_invoke_get_restaurants = async () => {
    const res =
      mode === 'handler' 
        ? await viaHandler({}, 'get-restaurants')
        : await viaHttp('restaurants', 'GET', { iam_auth: true })
  
    return res
  }
  
  module.exports = {
    we_invoke_get_index,
    we_invoke_get_restaurants,
    we_invoke_search_restaurants,
    we_invoke_place_order,
    we_invoke_notify_restaurant,
  }