// Copyright 2015 The Chromium OS 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 "libweave/examples/ubuntu/event_http_server.h"

#include <vector>

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

#include "libweave/examples/ubuntu/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;
}

bufferevent* BuffetEventCallback(event_base* base, void* arg) {
  SSL_CTX* ctx = static_cast<SSL_CTX*>(arg);
  return bufferevent_openssl_socket_new(
      base, -1, SSL_new(ctx), BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_CLOSE_ON_FREE);
}

class MemoryReadStream : public Stream {
 public:
  MemoryReadStream(const std::vector<uint8_t>& data, TaskRunner* task_runner)
      : data_{data}, task_runner_{task_runner} {}

  void Read(void* buffer,
            size_t size_to_read,
            const base::Callback<void(size_t)>& success_callback,
            const base::Callback<void(const Error*)>& error_callback) override {
    CHECK_LE(read_position_, data_.size());
    size_t size_read = std::min(size_to_read, data_.size() - read_position_);
    if (size_read > 0)
      memcpy(buffer, data_.data() + read_position_, size_read);
    read_position_ += size_read;
    success_callback.Run(size_read);
  }

  void Write(
      const void* buffer,
      size_t size_to_write,
      const base::Closure& success_callback,
      const base::Callback<void(const Error*)>& error_callback) override {
    LOG(FATAL) << "Unsupported";
  }

  void CancelPendingOperations() override {}

 private:
  const std::vector<uint8_t>& data_;
  TaskRunner* task_runner_;
  size_t read_position_{0};
};

}  // namespace

class HttpServerImpl::RequestImpl : public Request {
 public:
  explicit RequestImpl(evhttp_request* req, TaskRunner* task_runner)
      : path_{evhttp_request_uri(req)}, task_runner_{task_runner} {
    path_ = path_.substr(0, path_.find("?"));
    path_ = path_.substr(0, path_.find("#"));
    req_.reset(req);

    data_.resize(evbuffer_get_length(req_->input_buffer));
    evbuffer_remove(req_->input_buffer, data_.data(), data_.size());
  }

  ~RequestImpl() {}

  const std::string& GetPath() const override { return path_; }
  std::string GetFirstHeader(const std::string& name) const override {
    const char* header = evhttp_find_header(req_->input_headers, name.c_str());
    if (!header)
      return {};
    return header;
  }
  const std::vector<uint8_t>& GetData() const override { return data_; }
  std::unique_ptr<Stream> GetDataStream() const override {
    return std::unique_ptr<Stream>{new MemoryReadStream{data_, task_runner_}};
  }

  evhttp_request* ReleaseHandler() { return req_.release(); }

 private:
  std::vector<uint8_t> data_;
  std::unique_ptr<evhttp_request, decltype(&evhttp_cancel_request)> req_{
      nullptr, &evhttp_cancel_request};
  std::string path_;
  TaskRunner* task_runner_;
};

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

  ctx_.reset(SSL_CTX_new(TLSv1_2_server_method()));
  SSL_CTX_set_options(ctx_.get(), SSL_OP_SINGLE_DH_USE |
                                      SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_SSLv2);

  ec_key_.reset(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
  CHECK(ec_key_) << GetSslError();
  CHECK_EQ(1, SSL_CTX_set_tmp_ecdh(ctx_.get(), ec_key_.get())) << GetSslError();

  GenerateX509();
  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(evhttp_new(task_runner_->GetEventBase()));
  CHECK(httpd_);
  httpsd_.reset(evhttp_new(task_runner_->GetEventBase()));
  CHECK(httpsd_);

  evhttp_set_bevcb(httpsd_.get(), BuffetEventCallback, ctx_.get());
  evhttp_set_gencb(httpd_.get(), ProcessRequestCallback, this);
  evhttp_set_gencb(httpsd_.get(), ProcessRequestCallback, this);

  CHECK_EQ(0, evhttp_bind_socket(httpd_.get(), "0.0.0.0", GetHttpPort()));
  CHECK_EQ(0, evhttp_bind_socket(httpsd_.get(), "0.0.0.0", GetHttpsPort()));
}

void HttpServerImpl::GenerateX509() {
  x509_.reset(X509_new());
  CHECK(x509_) << GetSslError();

  X509_set_version(x509_.get(), 2);

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

  pkey_.reset(EVP_PKEY_new());
  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_.get(), rsa)) << GetSslError();

  X509_set_pubkey(x509_.get(), pkey_.get());

  CHECK(X509_sign(x509_.get(), pkey_.get(), EVP_sha256())) << GetSslError();

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

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

void HttpServerImpl::NotFound(evhttp_request* req) {
  std::unique_ptr<evbuffer, decltype(&evbuffer_free)> buf{evbuffer_new(),
                                                          &evbuffer_free};
  evbuffer_add_printf(buf.get(), "404 Not Found: %s\n",
                      evhttp_request_uri(req));
  evhttp_send_reply(req, 404, "Not Found", buf.get());
}

void HttpServerImpl::ProcessRequest(evhttp_request* req) {
  std::string path = evhttp_request_uri(req);
  for (auto i = handlers_.rbegin(); i != handlers_.rend(); ++i) {
    if (path.compare(0, i->first.size(), i->first) == 0) {
      auto request = std::make_shared<RequestImpl>(req, task_runner_);
      i->second.Run(*request,
                    base::Bind(&HttpServerImpl::ProcessReply,
                               weak_ptr_factory_.GetWeakPtr(), request));
      return;
    }
  }
  NotFound(req);
}
void HttpServerImpl::ProcessReply(std::shared_ptr<RequestImpl> request,
                                  int status_code,
                                  const std::string& data,
                                  const std::string& mime_type) {
  std::unique_ptr<evbuffer, decltype(&evbuffer_free)> buf{evbuffer_new(),
                                                          &evbuffer_free};
  evbuffer_add(buf.get(), data.data(), data.size());
  evhttp_request* req = request->ReleaseHandler();
  evhttp_add_header(req->output_headers, "Content-Type", mime_type.c_str());
  evhttp_send_reply(req, status_code, "None", buf.get());
}

void HttpServerImpl::AddOnStateChangedCallback(
    const OnStateChangedCallback& callback) {
  callback.Run(*this);
}

void HttpServerImpl::AddRequestHandler(const std::string& path_prefix,
                                       const OnRequestCallback& callback) {
  handlers_.emplace(path_prefix, callback);
}

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

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

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

}  // namespace examples
}  // namespace weave
