// 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.

#ifndef COBALT_WEBDRIVER_DISPATCHER_H_
#define COBALT_WEBDRIVER_DISPATCHER_H_

#include <string>
#include <vector>

#include "base/callback.h"
#include "base/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "base/optional.h"
#include "base/values.h"
#include "cobalt/webdriver/protocol/response.h"
#include "cobalt/webdriver/protocol/session_id.h"
#include "cobalt/webdriver/server.h"
#include "net/http/http_status_code.h"

namespace cobalt {
namespace webdriver {

// The WebDriverDispatcher maps URL paths to WebDriver command callbacks.
// The Dispatcher will take care of a number of types of Invalid requests and
// send a response to the server.
// TODO: Refactor such that the Dispatcher can detect all kinds of
//   invalid requests, such that the registered Callback for a given path will
//   only be called for valid requests.
// A registered URL can contain variable components, which are prefixed
// with a colon. The Dispatcher will create a PathVariableMap which maps these
// variable components of the path to the actual value in the request.
class WebDriverDispatcher {
 public:
  // A handle to an instance of this class is passed to registered command
  // callbacks. A URL path component that starts with a colon is recognized
  // as a variable component. Path variables for a given request can be looked
  // up using this structure.
  class PathVariableMap {
   public:
    std::string GetVariable(const std::string& variable_name) const {
      PathVariableMapInternal::const_iterator it =
          path_variable_map_.find(variable_name);
      if (it == path_variable_map_.end()) {
        NOTREACHED();
        return "";
      }
      return it->second;
    }

   protected:
    typedef base::hash_map<std::string, std::string> PathVariableMapInternal;
    explicit PathVariableMap(const PathVariableMapInternal& variable_map)
        : path_variable_map_(variable_map) {}
    const PathVariableMapInternal& path_variable_map_;
    friend class WebDriverDispatcher;
  };

  // An instance of this class is passed to WebDriver API command
  // implementations through the CommandCallback function.
  class CommandResultHandler {
   public:
    enum RequestError {
      kInvalidParameters,
      kInvalidPathVariable,
    };
    // Send the result of the execution of a registered WebDriver command to be
    // sent as a response as described in the spec:
    // https://code.google.com/p/selenium/wiki/JsonWireProtocol#Responses
    // https://code.google.com/p/selenium/wiki/JsonWireProtocol#Failed_Commands
    virtual void SendResult(
        const base::optional<protocol::SessionId>& session_id,
        protocol::Response::StatusCode status_code,
        scoped_ptr<base::Value> result) = 0;

    // Send data as a result of a command to the dispatcher. This is similar to
    // SendResult with the primary difference being the type of data can be of
    // any valid HTTP content type, specified with |content_type|. For example,
    // this could be used to send an image. Not used in any
    // commands in the WebDriver specification.
    virtual void SendResultWithContentType(
        protocol::Response::StatusCode status_code,
        const std::string& content_type, const char* data, int len) = 0;

    // Some forms of Invalid Requests are detected in the CommandCallback by
    // checking the path variables and command parameters. Invalid requests are
    // described here:
    // https://code.google.com/p/selenium/wiki/JsonWireProtocol#Invalid_Requests
    //
    // TODO: Invalid requests should be handled before calling the
    //   CommandCallback.
    virtual void SendInvalidRequestResponse(
        RequestError error, const std::string& error_string) = 0;

   protected:
    virtual ~CommandResultHandler() {}
    friend class scoped_ptr<CommandResultHandler>;
  };

  typedef base::Callback<void(const base::Value*, const PathVariableMap*,
                              scoped_ptr<CommandResultHandler>)>
      DispatchCommandCallback;

  // Register the Http method and path (with possible variable components) to
  // the specified callback.
  void RegisterCommand(WebDriverServer::HttpMethod method,
                       const std::string& path,
                       const DispatchCommandCallback& cb);

  // Find the DispatchCommandCallback that is mapped to the requested method
  // and path. If found, execute the command with the given request_body as the
  // command's parameters. The result of the request will be sent to the
  // WebDriverServer::ResponseHandler.
  void HandleWebDriverServerRequest(
      WebDriverServer::HttpMethod method, const std::string& path,
      scoped_ptr<base::Value> request_body,
      scoped_ptr<WebDriverServer::ResponseHandler> handler);

 private:
  enum MatchStrategy {
    kMatchExact,
    kMatchVariables,
  };
  // Internal structure that manages command mappings for a given URL.
  // Each Http method can have a DispatchCommmandCallback mapped to it.
  // The registered path is stored as a tokenized vector of the registered
  // path's components, preserving variable components that start with a colon.
  struct CommandMapping {
    explicit CommandMapping(const std::vector<std::string>& components)
        : path_components(components) {}

    std::vector<std::string> path_components;
    typedef base::hash_map<WebDriverServer::HttpMethod, DispatchCommandCallback>
        MethodToCommandMap;
    MethodToCommandMap command_map;
  };

  // Helper method to find a CommandMapping for a given path. Based on the
  // MatchStrategy, this could get the CommandMapping for the exact URL path,
  // or it could match variable components as wildcards.
  CommandMapping* GetMappingForPath(const std::vector<std::string>& components,
                                    MatchStrategy strategy);

  // Use the number of components in the registered path as a key to speed up
  // lookup, which is otherwise done linearly.
  typedef base::hash_multimap<int, CommandMapping> CommandMappingLookup;
  CommandMappingLookup command_lookup_;
};

}  // namespace webdriver
}  // namespace cobalt

#endif  // COBALT_WEBDRIVER_DISPATCHER_H_
