// Copyright 2014 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 "libwebserv/connection.h"

#include <algorithm>
#include <vector>

#include <base/bind.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/task_runner.h>
#include <chromeos/http/http_request.h>
#include <microhttpd.h>

#include "libwebserv/request.h"
#include "libwebserv/request_handler_interface.h"
#include "libwebserv/response.h"
#include "libwebserv/server.h"

namespace libwebserv {

// Helper class to provide static callback methods to microhttpd library,
// with the ability to access private methods of Connection class.
class ConnectionHelper {
 public:
  static int PostDataIterator(void* cls,
                              MHD_ValueKind kind,
                              const char* key,
                              const char* filename,
                              const char* content_type,
                              const char* transfer_encoding,
                              const char* data,
                              uint64_t off,
                              size_t size) {
    Connection* server_connection = reinterpret_cast<Connection*>(cls);
    if (!server_connection->ProcessPostData(
        key, filename, content_type, transfer_encoding, data, off, size)) {
      return MHD_NO;
    }
    return MHD_YES;
  }
};

// Helper class to provide static callback methods to microhttpd library,
// with the ability to access private methods of Request class.
class RequestHelper {
 public:
  static int ValueCallback(void* cls,
                           MHD_ValueKind kind,
                           const char* key,
                           const char* value) {
    auto self = reinterpret_cast<Request*>(cls);
    std::string data;
    if (value)
      data = value;
    if (kind == MHD_HEADER_KIND) {
      self->headers_.emplace(Request::GetCanonicalHeaderName(key), data);
    } else if (kind == MHD_COOKIE_KIND) {
      // TODO(avakulenko): add support for cookies...
    } else if (kind == MHD_POSTDATA_KIND) {
      self->post_data_.emplace(key, data);
    } else if (kind == MHD_GET_ARGUMENT_KIND) {
      self->get_data_.emplace(key, data);
    }
    return MHD_YES;
  }
};

Connection::Connection(const scoped_refptr<base::TaskRunner>& task_runner,
                       MHD_Connection* connection,
                       RequestHandlerInterface* handler)
    : task_runner_(task_runner),
      raw_connection_(connection),
      handler_(handler) {
}

Connection::~Connection() {
  if (post_processor_)
    MHD_destroy_post_processor(post_processor_);
}

scoped_refptr<Connection> Connection::Create(Server* server,
                                             const std::string& url,
                                             const std::string& method,
                                             MHD_Connection* connection,
                                             RequestHandlerInterface* handler) {
  scoped_refptr<Connection> result(
      new Connection(server->task_runner_, connection, handler));
  VLOG(1) << "Incoming HTTP connection (" << result.get() << ")."
          << " Method='" << method << "', URL='" << url << "'";
  result->post_processor_ = MHD_create_post_processor(
      connection, 1024, &ConnectionHelper::PostDataIterator, result.get());
  result->request_ = Request::Create(url, method);
  result->response_ = Response::Create(result);
  return result;
}

bool Connection::BeginRequestData() {
  MHD_get_connection_values(raw_connection_, MHD_HEADER_KIND,
                            &RequestHelper::ValueCallback, request_.get());
  MHD_get_connection_values(raw_connection_, MHD_COOKIE_KIND,
                            &RequestHelper::ValueCallback, request_.get());
  MHD_get_connection_values(raw_connection_, MHD_POSTDATA_KIND,
                            &RequestHelper::ValueCallback, request_.get());
  MHD_get_connection_values(raw_connection_, MHD_GET_ARGUMENT_KIND,
                            &RequestHelper::ValueCallback, request_.get());
  return true;
}

bool Connection::AddRequestData(const void* data, size_t size) {
  if (!post_processor_)
    return request_->AddRawRequestData(data, size);
  return MHD_post_process(post_processor_,
                          static_cast<const char*>(data), size) == MHD_YES;
}

void Connection::EndRequestData() {
  if (state_ == State::kIdle) {
    state_ = State::kRequestSent;
    // libmicrohttpd calls handlers on its own thread.
    // Redirect this to the main IO thread of the server.
    task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&RequestHandlerInterface::HandleRequest,
                   base::Unretained(handler_), base::Passed(&request_),
                   base::Passed(&response_)));
  } else if (state_ == State::kResponseReceived) {
    VLOG(1) << "Sending HTTP response for connection (" << this
            << "): " << response_status_code_
            << ", data size = " << response_data_.size();
    MHD_Response* resp = MHD_create_response_from_buffer(
        response_data_.size(), response_data_.data(), MHD_RESPMEM_PERSISTENT);
    for (const auto& pair : response_headers_) {
      MHD_add_response_header(resp, pair.first.c_str(), pair.second.c_str());
    }
    CHECK_EQ(MHD_YES,
             MHD_queue_response(raw_connection_, response_status_code_, resp))
        << "Failed to queue response";
    MHD_destroy_response(resp);  // |resp| is ref-counted.
    state_ = State::kDone;
  }
}

bool Connection::ProcessPostData(const char* key,
                                 const char* filename,
                                 const char* content_type,
                                 const char* transfer_encoding,
                                 const char* data,
                                 uint64_t off,
                                 size_t size) {
  if (off == 0)
    return  request_->AddPostFieldData(key, filename, content_type,
                                       transfer_encoding, data, size);
  return request_->AppendPostFieldData(key, data, size);
}

}  // namespace libwebserv
