/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 */
"use strict";

const CRLF = "\r\n";
const BOUNDARY = "3beqjf3apnqeu3h5jqorms4i";

class MultipartResponse {
  static wrap(req, res) {
    if (acceptsMultipartResponse(req)) {
      return new MultipartResponse(res);
    } // Ugly hack, ideally wrap function should always return a proxy
    // object with the same interface

    res.writeChunk = () => {}; // noop

    return res;
  }

  constructor(res) {
    this.res = res;
    this.headers = {};
    res.writeHead(200, {
      "Content-Type": `multipart/mixed; boundary="${BOUNDARY}"`
    });
    res.write(
      "If you are seeing this, your client does not support multipart response"
    );
  }

  writeChunk(headers, data) {
    let isLast =
      arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
    let chunk = `${CRLF}--${BOUNDARY}${CRLF}`;

    if (headers) {
      chunk += MultipartResponse.serializeHeaders(headers) + CRLF + CRLF;
    }

    if (data) {
      chunk += data;
    }

    if (isLast) {
      chunk += `${CRLF}--${BOUNDARY}--${CRLF}`;
    }

    if (!this.res.finished) {
      this.res.write(chunk);
    }
  }

  writeHead(status, headers) {
    // We can't actually change the response HTTP status code
    // because the headers have already been sent
    this.setHeader("X-Http-Status", status);

    if (!headers) {
      return;
    }

    for (const key in headers) {
      this.setHeader(key, headers[key]);
    }
  }

  setHeader(name, value) {
    this.headers[name] = value;
  }

  end(data) {
    this.writeChunk(this.headers, data, true);
    this.res.end();
  }

  static serializeHeaders(headers) {
    return Object.keys(headers)
      .map(key => `${key}: ${headers[key]}`)
      .join(CRLF);
  }
}

function acceptsMultipartResponse(req) {
  return req.headers && req.headers.accept === "multipart/mixed";
}

module.exports = MultipartResponse;