/*
  Copyright (c) DataStax, Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "http_server.hpp"

using datastax::String;
using datastax::internal::Memory;
using datastax::internal::OStringStream;
using datastax::internal::ScopedMutex;
using datastax::internal::core::Address;
using datastax::internal::core::EventLoop;
using datastax::internal::core::Task;

String response(int status, const String& body = "", const String& content_type = "") {
  OStringStream ss;
  ss << "HTTP/1.0 " << status << " " << http_status_str(static_cast<http_status>(status)) << "\r\n";
  if (!body.empty()) {
    ss << "Content-Type: ";
    if (content_type.empty()) {
      ss << "text/plain";
    } else {
      ss << content_type;
    }
    ss << "\r\nContent-Length: " << body.size() << "\r\n\r\n" << body;
  } else {
    ss << "\r\n";
  }

  return ss.str();
}

using namespace mockssandra;
using namespace mockssandra::http;

void Server::listen() {
  server_connection_->listen(&event_loop_group_);
  server_connection_->wait_listen();
}

void Server::close() {
  if (server_connection_) {
    server_connection_->close();
    server_connection_->wait_close();
  }
}

bool Server::use_ssl(const String& key, const String& cert, const String& ca_cert /*= ""*/,
                     bool require_client_cert /*= false*/) {
  return server_connection_->use_ssl(key, cert, ca_cert, require_client_cert);
}

Server::ClientConnection::ClientConnection(internal::ServerConnection* server_connection,
                                           Server* server)
    : internal::ClientConnection(server_connection)
    , path_(server->path())
    , content_type_(server->content_type())
    , response_body_(server->response_body())
    , response_status_code_(server->response_status_code())
    , enable_valid_response_(server->enable_valid_response())
    , close_connnection_after_request_(server->close_connnection_after_request()) {
  http_parser_init(&parser_, HTTP_REQUEST);
  http_parser_settings_init(&parser_settings_);

  parser_.data = this;
  parser_settings_.on_url = on_url;
}

void Server::ClientConnection::on_read(const char* data, size_t len) {
  request_ = String(data, len);
  size_t parsed = http_parser_execute(&parser_, &parser_settings_, data, len);
  if (parsed < static_cast<size_t>(len)) {
    enum http_errno err = HTTP_PARSER_ERRNO(&parser_);
    fprintf(stderr, "%s: %s\n", http_errno_name(err), http_errno_description(err));
    close();
  }
}

int Server::ClientConnection::on_url(http_parser* parser, const char* buf, size_t len) {
  ClientConnection* self = static_cast<ClientConnection*>(parser->data);
  self->handle_url(buf, len);
  return 0;
}

void Server::ClientConnection::handle_url(const char* buf, size_t len) {
  String path(buf, len);
  if (path.substr(0, path.find("?")) == path_) { // Compare without query parameters
    if (enable_valid_response_) {
      if (response_body_.empty()) {
        write(response(response_status_code_, request_)); // Echo response
      } else {
        write(response(response_status_code_, response_body_, content_type_));
      }
    } else {
      write("Invalid HTTP server response");
    }
  } else {
    write(response(404));
  }
  // From the HTTP/1.0 protocol specification:
  //
  // > When an Entity-Body is included with a message, the length of that body may be determined in
  // > one of two ways. If a Content-Length header field is present, its value in bytes represents
  // > the length of the Entity-Body. Otherwise, the body length is determined by the closing of the
  // > connection by the server.
  if (close_connnection_after_request_) {
    close();
  }
}
