// 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,
                   provider::TaskRunner* task_runner)
      : data_{data}, task_runner_{task_runner} {}

  void Read(void* buffer,
            size_t size_to_read,
            const ReadSuccessCallback& success_callback,
            const ErrorCallback& 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 SuccessCallback& success_callback,
             const ErrorCallback& error_callback) override {
    LOG(FATAL) << "Unsupported";
  }

  void CancelPendingOperations() override {}

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

}  // namespace

class HttpServerImpl::RequestImpl : public Request {
 public:
  explicit RequestImpl(evhttp_request* req, provider::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_;
  provider::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
