// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// 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 "cobalt/webdriver/server.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/string_util.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/tcp_listen_socket.h"
#include "net/server/http_server_request_info.h"

namespace cobalt {
namespace webdriver {
namespace {

const char kJsonContentType[] = "application/json;charset=UTF-8";
const char kTextPlainContentType[] = "text/plain";

WebDriverServer::HttpMethod StringToHttpMethod(const std::string& method) {
  if (LowerCaseEqualsASCII(method, "get")) {
    return WebDriverServer::kGet;
  } else if (LowerCaseEqualsASCII(method, "post")) {
    return WebDriverServer::kPost;
  } else if (LowerCaseEqualsASCII(method, "delete")) {
    return WebDriverServer::kDelete;
  }
  return WebDriverServer::kUnknownMethod;
}

std::string HttpMethodToString(WebDriverServer::HttpMethod method) {
  switch (method) {
    case WebDriverServer::kGet:
      return "GET";
    case WebDriverServer::kPost:
      return "POST";
    case WebDriverServer::kDelete:
      return "DELETE";
    case WebDriverServer::kUnknownMethod:
      return "UNKNOWN";
  }
  NOTREACHED();
  return "";
}

// Implementation of the ResponseHandler interface.
// A Delegate implementation will call the methods on this interface for
// successful, failed, and invalid requests.
// For each of these cases, prepare an appropriate Http Response according to
// the spec, and send it to the specified connection through the net::HttpServer
// instance.
class ResponseHandlerImpl : public WebDriverServer::ResponseHandler {
 public:
  ResponseHandlerImpl(const scoped_refptr<net::HttpServer>& server,
                      int connection_id)
      : server_message_loop_(base::MessageLoopProxy::current()),
        server_(server),
        connection_id_(connection_id) {}

  // https://code.google.com/p/selenium/wiki/JsonWireProtocol#Responses
  void Success(scoped_ptr<base::Value> value) override {
    DCHECK(value);
    std::string data;
    base::JSONWriter::Write(value.get(), &data);
    SendInternal(net::HTTP_OK, data, kJsonContentType);
  }

  // Failed commands map to a valid WebDriver command and contain the expected
  // parameters, but otherwise failed to execute for some reason. This should
  // send a 500 Internal Server Error.
  // https://code.google.com/p/selenium/wiki/JsonWireProtocol#Error_Handling
  void FailedCommand(scoped_ptr<base::Value> value) override {
    DCHECK(value);
    std::string data;
    base::JSONWriter::Write(value.get(), &data);
    SendInternal(net::HTTP_INTERNAL_SERVER_ERROR, data, kJsonContentType);
  }

  // A number of cases for invalid requests are explained here:
  // https://code.google.com/p/selenium/wiki/JsonWireProtocol#Invalid_Requests
  // The response type should be text/plain and the message body is an error
  // message

  // The command request is not mapped to anything.
  void UnknownCommand(const std::string& path) override {
    LOG(INFO) << "Unknown command: " << path;
    SendInternal(net::HTTP_NOT_FOUND, "Unknown command",
                 kTextPlainContentType);
  }

  // The command request is mapped to a valid command, but this WebDriver
  // implementation has not implemented it.
  void UnimplementedCommand(const std::string& path) override {
    LOG(INFO) << "Unimplemented command: " << path;
    SendInternal(net::HTTP_NOT_IMPLEMENTED, "Unimplemented command",
                 kTextPlainContentType);
  }

  // The request maps to a valid command, but the variable part of the path
  // does not map to a valid instance.
  void VariableResourceNotFound(const std::string& variable_name) override {
    SendInternal(net::HTTP_NOT_FOUND,
                 "Unknown variable resource: " + variable_name,
                 kTextPlainContentType);
  }

  // The request maps to a valid command, but with an unsupported Http method.
  void InvalidCommandMethod(WebDriverServer::HttpMethod requested_method,
                            const std::vector<WebDriverServer::HttpMethod>&
                                allowed_methods) override {
    DCHECK(!allowed_methods.empty());
    std::vector<std::string> allowed_method_strings;
    for (int i = 0; i < allowed_methods.size(); ++i) {
      allowed_method_strings.push_back(HttpMethodToString(allowed_methods[i]));
    }
    std::vector<std::string> headers;
    headers.push_back("Allow: " + JoinString(allowed_method_strings, ", "));
    SendInternal(net::HTTP_METHOD_NOT_ALLOWED,
                 "Invalid method: " + HttpMethodToString(requested_method),
                 kTextPlainContentType, headers);
  }

  // The POST command's JSON request body does not contain the required
  // parameters.
  void MissingCommandParameters(const std::string& message) override {
    SendInternal(net::HTTP_BAD_REQUEST, message, kTextPlainContentType);
  }

 private:
  static void SendToServer(const scoped_refptr<net::HttpServer>& server,
                           int connection_id, net::HttpStatusCode status,
                           const std::string& message,
                           const std::string& content_type,
                           const std::vector<std::string>& headers) {
    server->Send(connection_id, status, message, content_type, headers);
  }

  // Send response with no additional headers specified.
  void SendInternal(net::HttpStatusCode status, const std::string& message,
                    const std::string& content_type) {
    std::vector<std::string> headers;
    SendInternal(status, message, content_type, headers);
  }

  // Send a response on the Http Server's thread.
  void SendInternal(net::HttpStatusCode status, const std::string& message,
                    const std::string& content_type,
                    const std::vector<std::string>& headers) {
    if (base::MessageLoopProxy::current() == server_message_loop_) {
      SendToServer(server_, connection_id_, status, message, content_type,
                   headers);
    } else {
      base::Closure closure =
          base::Bind(&SendToServer, server_, connection_id_, status, message,
                     content_type, headers);
      server_message_loop_->PostTask(FROM_HERE, closure);
    }
  }

  scoped_refptr<base::MessageLoopProxy> server_message_loop_;
  scoped_refptr<net::HttpServer> server_;
  int connection_id_;
};
}  // namespace

WebDriverServer::WebDriverServer(int port, const std::string& listen_ip,
                                 const HandleRequestCallback& callback)
    : handle_request_callback_(callback),
      server_address_("Cobalt.Server.WebDriver",
                      "Address to communicate with WebDriver.") {
  // Create http server
  factory_.reset(new net::TCPListenSocketFactory(listen_ip, port));
  server_ = new net::HttpServer(*factory_, this);
  GURL address;
  int result = GetLocalAddress(&address);
  if (result == net::OK) {
    LOG(INFO) << "Starting WebDriver server on port " << port;
    server_address_ = address.spec();
  } else {
    LOG(WARNING) << "Could not start WebDriver server";
    server_address_ = "<NOT RUNNING>";
  }
}

void WebDriverServer::OnHttpRequest(int connection_id,
                                    const net::HttpServerRequestInfo& info) {
  TRACE_EVENT0("cobalt::webdriver", "WebDriverServer::OnHttpRequest()");

  DCHECK(thread_checker_.CalledOnValidThread());
  std::string path = info.path;
  size_t query_position = path.find("?");
  // Discard any URL variables from the path
  if (query_position != std::string::npos) {
    path.resize(query_position);
  }

  DLOG(INFO) << "Got request: " << path;
  // Create a new ResponseHandler that will send a response to this connection.
  scoped_ptr<ResponseHandler> response_handler(
      new ResponseHandlerImpl(server_, connection_id));

  scoped_ptr<base::Value> parameters;
  HttpMethod method = StringToHttpMethod(info.method);
  if (method == kPost) {
    base::JSONReader reader;
    parameters.reset(reader.ReadToValue(info.data));
    if (!parameters) {
      // Failed to parse request body as JSON.
      response_handler->MissingCommandParameters(reader.GetErrorMessage());
      return;
    }
  }

  // Call the HandleRequestCallback.
  handle_request_callback_.Run(StringToHttpMethod(info.method), path,
                               parameters.Pass(), response_handler.Pass());
}

int WebDriverServer::GetLocalAddress(GURL* out) const {
  net::IPEndPoint ip_addr;
  int result = server_->GetLocalAddress(&ip_addr);
  if (result == net::OK) {
    *out = GURL("http://" + ip_addr.ToString());
  }
  return result;
}

}  // namespace webdriver
}  // namespace cobalt
