// Copyright 2015 The Weave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "examples/provider/event_http_server.h"

#include <vector>

#include <base/bind.h>
#include <base/time/time.h>
#include <event2/bufferevent_ssl.h>
#include <evhtp.h>
#include <openssl/err.h>

#include "examples/provider/event_task_runner.h"

namespace weave {
namespace examples {

namespace {

std::string GetSslError() {
  char error[1000] = {};
  ERR_error_string_n(ERR_get_error(), error, sizeof(error));
  return error;
}

}  // namespace

class HttpServerImpl::RequestImpl : public Request {
 public:
  RequestImpl(EventPtr<evhtp_request_t> req) : req_(std::move(req)) {
    evbuf_t* input_buffer = req_.get()->buffer_in;
    data_.resize(evbuffer_get_length(input_buffer));
    evbuffer_remove(input_buffer, &data_[0], data_.size());
  }

  ~RequestImpl() {}

  std::string GetPath() const override { return req_->uri->path->full; }

  std::string GetFirstHeader(const std::string& name) const override {
    const char* header = evhtp_header_find(req_->headers_in, name.c_str());
    if (!header)
      return {};
    return header;
  }

  std::string GetData() { return data_; }

  void SendReply(int status_code,
                 const std::string& data,
                 const std::string& mime_type) override {
    EventPtr<evbuffer> buf{evbuffer_new()};
    evbuffer_add(buf.get(), data.data(), data.size());
    evhtp_header_key_add(req_->headers_out, "Content-Type", 0);
    evhtp_header_val_add(req_->headers_out, mime_type.c_str(), 1);
    evhtp_header_key_add(req_->headers_out, "Content-Length", 0);
    std::string content_length = std::to_string(evbuffer_get_length(buf.get()));
    evhtp_header_val_add(req_->headers_out, content_length.c_str(), 1);
    evhtp_send_reply_start(req_.get(), status_code);
    evhtp_send_reply_body(req_.get(), buf.get());
    evhtp_send_reply_end(req_.get());
  }

 private:
  EventPtr<evhtp_request_t> req_;
  std::string data_;
};

HttpServerImpl::HttpServerImpl(EventTaskRunner* task_runner)
    : task_runner_{task_runner} {
  SSL_load_error_strings();
  SSL_library_init();

  std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ctx{
      SSL_CTX_new(TLSv1_2_server_method()), &SSL_CTX_free};
  CHECK(ctx);
  SSL_CTX_set_options(ctx.get(), SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE |
                                     SSL_OP_NO_SSLv2);

  std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> ec_key{
      EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), &EC_KEY_free};
  CHECK(ec_key) << GetSslError();
  CHECK_EQ(1, SSL_CTX_set_tmp_ecdh(ctx.get(), ec_key.get())) << GetSslError();

  std::unique_ptr<X509, decltype(&X509_free)> x509{X509_new(), &X509_free};
  CHECK(x509);
  std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> pkey{EVP_PKEY_new(),
                                                           &EVP_PKEY_free};
  CHECK(pkey);
  GenerateX509(x509.get(), pkey.get());
  CHECK_EQ(1, SSL_CTX_use_PrivateKey(ctx.get(), pkey.get())) << GetSslError();
  CHECK_EQ(1, SSL_CTX_use_certificate(ctx.get(), x509.get())) << GetSslError();

  CHECK_EQ(1, SSL_CTX_check_private_key(ctx.get())) << GetSslError();

  httpd_.reset(evhtp_new(task_runner_->GetEventBase(), nullptr));
  CHECK(httpd_);
  httpsd_.reset(evhtp_new(task_runner_->GetEventBase(), nullptr));
  CHECK(httpsd_);

  httpsd_.get()->ssl_ctx = ctx.release();

  CHECK_EQ(0, evhtp_bind_socket(httpd_.get(), "0.0.0.0", GetHttpPort(), -1));
  CHECK_EQ(0, evhtp_bind_socket(httpsd_.get(), "0.0.0.0", GetHttpsPort(), -1));
}

void HttpServerImpl::GenerateX509(X509* x509, EVP_PKEY* pkey) {
  CHECK(x509) << GetSslError();

  X509_set_version(x509, 2);

  X509_gmtime_adj(X509_get_notBefore(x509), 0);
  X509_gmtime_adj(X509_get_notAfter(x509),
                  base::TimeDelta::FromDays(365).InSeconds());

  CHECK(pkey) << GetSslError();
  std::unique_ptr<BIGNUM, decltype(&BN_free)> big_num(BN_new(), &BN_free);
  CHECK(BN_set_word(big_num.get(), 65537)) << GetSslError();
  auto rsa = RSA_new();
  RSA_generate_key_ex(rsa, 2048, big_num.get(), nullptr);
  CHECK(EVP_PKEY_assign_RSA(pkey, rsa)) << GetSslError();

  X509_set_pubkey(x509, pkey);

  CHECK(X509_sign(x509, pkey, EVP_sha256())) << GetSslError();

  cert_fingerprint_.resize(EVP_MD_size(EVP_sha256()));
  uint32_t len = 0;
  CHECK(X509_digest(x509, EVP_sha256(), cert_fingerprint_.data(), &len));
  CHECK_EQ(len, cert_fingerprint_.size());
}

void HttpServerImpl::NotFound(evhtp_request_t* req) {
  EventPtr<evbuffer> buf{evbuffer_new()};
  evbuffer_add_printf(buf.get(), "404 Not Found: %s\n", req->uri->path->full);
  evhtp_send_reply_start(req, 404);
  evhtp_send_reply_body(req, buf.get());
  evhtp_send_reply_end(req);
}

void HttpServerImpl::ProcessRequest(evhtp_request_t* req) {
  std::unique_ptr<RequestImpl> request{new RequestImpl{EventPtr<evhtp_request_t>{req}}};
  std::string path = request->GetPath();
  auto it = handlers_.find(std::make_pair(path, req->htp));
  if (it != handlers_.end()) {
    return it->second.Run(std::move(request));
  }
  NotFound(req);
}

void HttpServerImpl::ProcessRequestCallback(evhtp_request_t* req, void* arg) {
  static_cast<HttpServerImpl*>(arg)->ProcessRequest(req);
}

void HttpServerImpl::AddHttpRequestHandler(
    const std::string& path,
    const RequestHandlerCallback& callback) {
  handlers_[std::make_pair(path, httpd_.get())] = callback;
  evhtp_set_cb(httpd_.get(), path.c_str(), &ProcessRequestCallback, this);
}

void HttpServerImpl::AddHttpsRequestHandler(
    const std::string& path,
    const RequestHandlerCallback& callback) {
  handlers_[std::make_pair(path, httpsd_.get())] = callback;
  evhtp_set_cb(httpsd_.get(), path.c_str(), &ProcessRequestCallback, this);
}

void HttpServerImpl::RemoveHttpRequestHandler(const std::string& path) {
  handlers_.erase(std::make_pair(path, httpd_.get()));
  evhtp_set_cb(httpd_.get(), path.c_str(), nullptr, nullptr);
}

void HttpServerImpl::RemoveHttpsRequestHandler(const std::string& path) {
  handlers_.erase(std::make_pair(path, httpsd_.get()));
  evhtp_set_cb(httpsd_.get(), path.c_str(), nullptr, nullptr);
}

void HttpServerImpl::ProcessReply(std::shared_ptr<RequestImpl> request,
                                  int status_code,
                                  const std::string& data,
                                  const std::string& mime_type) {}

uint16_t HttpServerImpl::GetHttpPort() const {
  return 7780;
}

uint16_t HttpServerImpl::GetHttpsPort() const {
  return 7781;
}

base::TimeDelta HttpServerImpl::GetRequestTimeout() const {
  return base::TimeDelta::Max();
}

std::vector<uint8_t> HttpServerImpl::GetHttpsCertificateFingerprint() const {
  return cert_fingerprint_;
}

}  // namespace examples
}  // namespace weave
