/*
 * Copyright 2015 Google Inc. 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/dispatcher.h"

#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "cobalt/webdriver/protocol/response.h"

namespace cobalt {
namespace webdriver {
namespace {

const char kVariablePrefix = ':';

// CommandResultHandler implementation that sends the results of a
// WebDriver command to a WebDriverServer::ResponseHandler.
class CommandResultHandlerImpl
    : public WebDriverDispatcher::CommandResultHandler {
 public:
  CommandResultHandlerImpl(
      scoped_ptr<WebDriverServer::ResponseHandler> response_handler)
      : response_handler_(response_handler.Pass()) {}

  void SendResult(const base::optional<protocol::SessionId>& session_id,
                  protocol::Response::StatusCode status_code,
                  scoped_ptr<base::Value> webdriver_response_value) OVERRIDE {
    scoped_ptr<base::Value> response = protocol::Response::CreateResponse(
        session_id, status_code, webdriver_response_value.Pass());
    if (status_code == protocol::Response::kSuccess) {
      response_handler_->Success(response.Pass());
    } else {
      response_handler_->FailedCommand(response.Pass());
    }
  }

  void SendInvalidRequestResponse(RequestError error,
                                  const std::string& error_string) OVERRIDE {
    switch (error) {
      case kInvalidParameters:
        response_handler_->MissingCommandParameters(error_string);
        break;
      case kInvalidPathVariable:
        response_handler_->VariableResourceNotFound(error_string);
        break;
    }
  }

 private:
  scoped_ptr<WebDriverServer::ResponseHandler> response_handler_;
};

// Helper function to get all supported methods for a given mapping of
// HttpMethod to DispatchCommandCallback.
typedef base::hash_map<WebDriverServer::HttpMethod,
                       WebDriverDispatcher::DispatchCommandCallback>
    MethodToCommandMap;
std::vector<WebDriverServer::HttpMethod> GetAvailableMethods(
    const MethodToCommandMap& method_lookup) {
  std::vector<WebDriverServer::HttpMethod> available_methods;
  for (MethodToCommandMap::const_iterator it = method_lookup.begin();
       it != method_lookup.end(); ++it) {
    available_methods.push_back(it->first);
  }
  return available_methods;
}

// Populate a PathVariableMapInternal mapping based on the components of a
// registered URL and a requested path.
// The key of the map will be the name of the variable component, and the value
// will be the actual value of the corresponding component in the request.
typedef base::hash_map<std::string, std::string> PathVariableMapInternal;
void PopulatePathVariableMap(PathVariableMapInternal* path_variable_map,
                             const std::vector<std::string>& request,
                             const std::vector<std::string>& path_components) {
  DCHECK_EQ(path_components.size(), request.size());
  for (size_t i = 0; i < request.size(); ++i) {
    DCHECK(!path_components[i].empty());
    // If the path component starts with a colon, it is a variable. Map the
    // variable name (dropping the colon) to the actual value in the request.
    if (path_components[i][0] == kVariablePrefix) {
      (*path_variable_map)[path_components[i]] = request[i];
    }
  }
}

// Tokenize a URL path by component.
std::vector<std::string> TokenizePath(const std::string& path) {
  std::vector<std::string> tokenized_path;
  StringTokenizer tokenizer(path, "/");
  while (tokenizer.GetNext()) {
    tokenized_path.push_back(tokenizer.token());
  }
  return tokenized_path;
}

// Used to compare two path components. If match_exact is set to false,
// then if either path is a variable component (starts with ':'), they will
// trivially match.
class PathComponentsAreEqualPredicate {
 public:
  explicit PathComponentsAreEqualPredicate(bool match_exact)
      : match_exact_(match_exact) {}

  bool operator()(const std::string& lhs, const std::string& rhs) const {
    if (!match_exact_ && (StartsWithColon(lhs) || StartsWithColon(rhs))) {
      return true;
    }
    return lhs == rhs;
  }

 private:
  bool StartsWithColon(const std::string& s) const {
    return !s.empty() && s[0] == kVariablePrefix;
  }
  bool match_exact_;
};

}  // namespace

void WebDriverDispatcher::RegisterCommand(
    WebDriverServer::HttpMethod method, const std::string& path,
    const DispatchCommandCallback& callback) {
  // Break the registered path into components.
  std::vector<std::string> tokenized_path = TokenizePath(path);
  // Find the registered CommandMapping struct if any other methods have been
  // registered for this path yet. Use exact matching so that we don't match
  // any path variables as wildcards.
  CommandMapping* mapping = GetMappingForPath(tokenized_path, kMatchExact);
  if (!mapping) {
    // No commands registered for this path yet, so create a new CommandMapping.
    CommandMappingLookup::iterator it = command_lookup_.insert(
        std::make_pair(tokenized_path.size(), CommandMapping(tokenized_path)));
    mapping = &it->second;
  }

  // Register this Http method for this CommandMapping.
  CommandMapping::MethodToCommandMap& method_to_command_map =
      mapping->command_map;
  DCHECK(method_to_command_map.end() == method_to_command_map.find(method));
  method_to_command_map[method] = callback;
}

WebDriverDispatcher::CommandMapping* WebDriverDispatcher::GetMappingForPath(
    const std::vector<std::string>& components, MatchStrategy strategy) {
  // Use reverse iterators for the match so we can early-out of a mismatch
  // more quickly. Most requests start with '/session/:sessionId/', for
  // example.
  typedef std::pair<std::vector<std::string>::const_reverse_iterator,
                    std::vector<std::string>::const_reverse_iterator>
      MismatchResultPair;
  typedef std::pair<CommandMappingLookup::iterator,
                    CommandMappingLookup::iterator> EqualRangeResultPair;

  PathComponentsAreEqualPredicate predicate(strategy == kMatchExact);

  // First find all commands that have the same number of components.
  EqualRangeResultPair pair_range =
      command_lookup_.equal_range(components.size());

  // For each command mapping that has the correct number of components,
  // check if the components match the CommandMapping's components.
  for (CommandMappingLookup::iterator it = pair_range.first;
       it != pair_range.second; ++it) {
    DCHECK_EQ(components.size(), it->second.path_components.size());
    // mismatch will return a pair of iterators to the first item in each
    // sequence that is not equal.
    MismatchResultPair result_pair =
        std::mismatch(components.rbegin(), components.rend(),
                      it->second.path_components.rbegin(), predicate);
    if (result_pair.first == components.rend()) {
      DCHECK(result_pair.second == it->second.path_components.rend());
      return &it->second;
    }
  }
  return NULL;
}

void WebDriverDispatcher::HandleWebDriverServerRequest(
    WebDriverServer::HttpMethod method, const std::string& path,
    scoped_ptr<base::Value> request_value,
    scoped_ptr<WebDriverServer::ResponseHandler> response_handler) {
  // Tokenize the requested resource path and look up a CommandMapping for it,
  // matching variables.
  std::vector<std::string> tokenized_request = TokenizePath(path);
  const CommandMapping* command_mapping =
      GetMappingForPath(tokenized_request, kMatchVariables);

  if (command_mapping == NULL) {
    // No commands were registered to this path.
    response_handler->UnknownCommand(path);
    return;
  }

  CommandMapping::MethodToCommandMap::const_iterator command_it =
      command_mapping->command_map.find(method);
  if (command_it == command_mapping->command_map.end()) {
    // The requested URL maps to a known command, but not with the requested
    // method.
    response_handler->InvalidCommandMethod(
        method, GetAvailableMethods(command_mapping->command_map));
    return;
  }

  // Convert any variable components of the path to a mapping.
  PathVariableMapInternal path_variables;
  PopulatePathVariableMap(&path_variables, tokenized_request,
                          command_mapping->path_components);
  PathVariableMap path_variable_map(path_variables);

  // Create a new CommandResultHandler that will be passed to the Command
  // callback, and run the callback.
  scoped_ptr<CommandResultHandler> result_handler(
      new CommandResultHandlerImpl(response_handler.Pass()));
  command_it->second.Run(request_value.get(), &path_variable_map,
                         result_handler.Pass());
}


}  // namespace webdriver
}  // namespace cobalt
