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

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