text: const _ = require('lodash');
  const BaseHandler = require('./base');
  const { messages } = require('elasticio-node'); //@todo: replace with OIH???
  const MessagePublishers = require('../message-publishers');
  const assert = require('assert');
  const uuid = require('uuid/v1');
  
  const REQUEST_FIELDS = [
      'headers',
      'url',
      'method',
      'originalUrl',
      'query',
      'body'
  ];
  
  /**
   * Configuration object for a client response.
   * @typedef {Object} ClientResponseConfig
   * @param {number} status - http response status code.
   * @param {Object} headers - http response headers.
   * @param {(Object|string|number)} - http response body.
   */
  
  /**
   * Post webhook request handler.
   */
  class PostHandler extends BaseHandler {
      /**
       * @param req - express request object
       * @param res - express response object
       * @param {MessagePublisher} messagePublisher
       */
      constructor(req, res, messagePublisher) {
          super(req, res);
          assert(
              messagePublisher instanceof MessagePublishers.Base,
              'messagePublisher has to be an instance of MessagePublisher'
          );
          this._messagePublisher = messagePublisher;
      }
  
      /**
       * Handle request.
       * @returns {Promise<void>}
       */
      async handle() {
          await this.authorize();
          const msg = await this.createMessageFromPayload();
          const msgOpts = await this.createMessageOptions();
          const result = await this.sendMessageForExecution(msg, msgOpts);
          await this.sendResponse(result);
      }
  
      /**
       * Authorizes a request.
       * @throws an arrow if not authorized.
       * @returns {Promise<void>}
       */
      async authorize() {
          return;
      }
  
      /**
       * Parse incoming request and create a Message object based on it.
       * @returns {Message}
       */
      async createMessageFromPayload() {
          const req = this._req;
          const log = this.getLogger();
          log.trace('Creating webhook msg from request');
  
          const msg = messages.newEmptyMessage();
  
          _.each(REQUEST_FIELDS, (key) => {
              msg[key] = req[key];
          });
  
          msg.params = {};
  
          _.each(req.route.keys, (key) => {
              msg.params[key.name] = req.param(key.name);
          });
  
          //extracting pathSuffix from url that may contain get parameters
          msg.pathSuffix = req.path.replace(new RegExp(`/hook/${req.params.taskId}`, 'g'), '');
  
          if (typeof msg.body === 'string' || Buffer.isBuffer(msg.body)) {
              // Body should be JSON object and not string and not buffer
              msg.body = {};
          }
  
          if (req.method === 'GET') {
              msg.body = req.query;
          }
  
          log.debug({ msg: msg }, 'Message to be pushed to the webhook queue');
  
          return msg;
      }
  
      /**
       * Create message options object.
       * @returns {Promise<Object>}
       */
      async createMessageOptions() {
          const headers = {
              taskId: this.getFlow().id,
              execId: uuid().replace(/-/g, ''),
              userId: 'DOES_NOT_MATTER'
          };
          return { headers };
      }
  
      /**
       * Send a webhook message for execution.
       * @param {Message} msg
       * @param {Object} msgOpts
       * @returns {Promise<ClientResponseConfig>}
       */
      async sendMessageForExecution(msg, msgOpts) {
          const flow = this.getFlow();
          await this._messagePublisher.publish(flow, msg, msgOpts);
          return this.getResponse();
      }
  
      /**
       * Return client response configuration object.
       * @returns {Promise<ClientResponseConfig>}
       */
      async getResponse() {
          return {
              status: 200,
              headers: {
                  'content-type': 'application/json'
              },
              body: {
                  requestId: this.getRequestId(),
                  message: 'thank you'
              }
          };
      }
  
      /**
       * Respond to client.
       * @param {ClientResponseConfig}
       * @returns {Promise<void>}
       */
      async sendResponse({ status = 200, headers = {}, body = {} }) {
          this._res.status(status).set(headers).send(body);
      }
  }
  
  module.exports = PostHandler;
  