// 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_UTIL_DISPATCH_COMMAND_FACTORY_H_
#define COBALT_WEBDRIVER_UTIL_DISPATCH_COMMAND_FACTORY_H_

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"

namespace cobalt {
namespace webdriver {
namespace util {
namespace internal {

// Convert a value to a base::Value to return it as a part of the WebDriver
// response object.
template <typename T>
scoped_ptr<base::Value> ToValue(const T& value) {
  return T::ToValue(value);
}

template <typename T>
scoped_ptr<base::Value> ToValue(const std::vector<T>& value) {
  scoped_ptr<base::ListValue> list_value(new base::ListValue());
  for (int i = 0; i < value.size(); ++i) {
    list_value->Append(ToValue<T>(value[i]).release());
  }
  return list_value.PassAs<base::Value>();
}

// Partial template specialization for base::optional.
template <typename T>
scoped_ptr<base::Value> ToValue(const base::optional<T>& value) {
  if (value) {
    return ToValue<T>(*value);
  } else {
    return make_scoped_ptr<base::Value>(base::Value::CreateNullValue());
  }
}

// Template specialization for std::string.
template <>
scoped_ptr<base::Value> ToValue(const std::string& value) {
  return make_scoped_ptr<base::Value>(new base::StringValue(value));
}

// Template specialization for bool.
template <>
scoped_ptr<base::Value> ToValue(const bool& value) {
  return make_scoped_ptr<base::Value>(new base::FundamentalValue(value));
}

template <typename R>
scoped_ptr<base::Value> ToValue(const CommandResult<R>& command_result) {
  return ToValue(command_result.result());
}

template <>
scoped_ptr<base::Value> ToValue(const CommandResult<void>& command_result) {
  return make_scoped_ptr(base::Value::CreateNullValue());
}

// Convert a base::Value to a base::optional<T>. If value could not be converted
// base::nullopt will be returned.
template <typename T>
base::optional<T> FromValue(const base::Value* value) {
  return T::FromValue(value);
}

template <>
base::optional<GURL> FromValue(const base::Value* value) {
  const char kUrlKey[] = "url";
  std::string url;
  const base::DictionaryValue* dictionary_value;
  if (!value->GetAsDictionary(&dictionary_value) ||
      !dictionary_value->GetString(kUrlKey, &url)) {
    return base::nullopt;
  }
  return GURL(url.c_str());
}

// Returns an appropriate response through the CommandResultHandler.
// On failure, the error response value is created and on success the
// result in the CommandResult instance is converted to a base::Value and
// returned.
template <typename R>
void ReturnResponse(const base::optional<protocol::SessionId>& session_id,
                    const util::CommandResult<R>& command_result,
                    WebDriverDispatcher::CommandResultHandler* result_handler) {
  scoped_ptr<base::Value> result;
  if (command_result.is_success()) {
    result = internal::ToValue(command_result);
  } else {
    result =
        protocol::Response::CreateErrorResponse(command_result.error_message());
  }
  result_handler->SendResult(session_id, command_result.status_code(),
                             result.Pass());
}

}  // namespace internal

// Helper class to create WebDriverDispatcher::DispatchCommandCallbacks that
// can be used with the WebDriverDispatcher::RegisterCommand function.
// Specify the XXXDriver class name as a template parameter.
template <class DriverClassT>
class DispatchCommandFactory
    : public base::RefCounted<DispatchCommandFactory<DriverClassT> > {
  // Max retries for the "can_retry" CommandResult case.
  static const int kMaxRetries = 5;

 public:
  // Typedef'd for less verbose code.
  typedef WebDriverDispatcher::CommandResultHandler CommandResultHandler;
  typedef WebDriverDispatcher::DispatchCommandCallback DispatchCommandCallback;
  typedef WebDriverDispatcher::PathVariableMap PathVariableMap;

  // Callback that takes PathVariableMap* and CommandResultHandler* as arguments
  // and returns a SessionDriver*.
  // Attempts to extract the sessionID from the PathVariableMap and finds the
  // session that this ID maps to. If no such session occurrs, an error is sent
  // through the CommandResultHandler and NULL is returned.
  typedef base::Callback<SessionDriver*(const PathVariableMap* path_variables,
                                        CommandResultHandler*)>
      GetSessionCommand;

  // Callback that takes PathVariableMap* and CommandResultHandler* as arguments
  // and returns a DriverClass*.
  // If necessary extracts the id from the PathVariableMap and finds the driver
  // that this ID maps to. If no such driver occurs, an error is sent through
  // the CommandResultHandler and NULL is returned.
  typedef base::Callback<DriverClassT*(SessionDriver*,
                                       const PathVariableMap* path_variables,
                                       CommandResultHandler*)> GetDriverCommand;

  // Takes GetSessionCommand and GetDriverCommand callbacks. These will be
  // called when the DispatchCommandCallback is called to try to find the
  // correct XXXDriver based on the path variables.
  DispatchCommandFactory(const GetSessionCommand& get_session,
                         const GetDriverCommand& get_driver)
      : get_session_(get_session), get_driver_(get_driver) {}

  // Returns a DispatchCommandCallback that will call the specified
  // command_callback.
  // If the path variables successfull map to a DriverClass instance, it will
  // be passed as the argument to the command_callback.
  // If no such DriverClass instance can be found, the command_callback will not
  // be run. The results of the command will be sent through the
  // CommandResultHandler.
  template <typename R>
  DispatchCommandCallback GetCommandHandler(
      const base::Callback<util::CommandResult<R>(DriverClassT*)>&
          command_callback) {
    typedef CommandHandler<R> CommandHandler;
    return CommandHandler::GetCommandHandler(
        get_session_, get_driver_,
        base::Bind(&CommandHandler::RunCommand, command_callback));
  }

  // Returns a DispatchCommandCallback that will call the specified
  // command_callback with an argument.
  // If the path variables successfull map to a DriverClass instance, it will
  // be passed as the argument to the command_callback.
  // If the parameters passed to the command cannot be converted to an instance
  // of type A1, the command_callback will not be called an an appropriate
  // error will be returned through the CommandRequestHandler.
  // If no such DriverClass instance can be found, the command_callback will not
  // be run.
  template <typename R, typename A1>
  DispatchCommandCallback GetCommandHandler(
      const base::Callback<util::CommandResult<R>(DriverClassT*, const A1&)>&
          command_callback) {
    typedef CommandHandler<R> CommandHandler;
    return CommandHandler::GetCommandHandler(
        get_session_, get_driver_,
        base::Bind(&CommandHandler::template ExtractParameterAndRunCommand<A1>,
                   command_callback));
  }

 private:
  // Works with the DispatchCommandFactory to create a DispatchCommandCallback
  // for a particular return value R. Putting this into a nested template class
  // helps alleviate some of the headaches of working with C++ templates.
  template <typename R>
  class CommandHandler : public base::RefCounted<CommandHandler<R> > {
   public:
    // Wrapper around an actual command to run. It will extract arguments from
    // |parameters| if necessary and pass them to the command.
    // If parameters cannot be extracted, an appropriate error will be sent to
    // the CommandResultHandler.
    // Upon successful completion of the command, the result will be sent to
    // CommandResultHandler.
    typedef base::Callback<void(
        const base::optional<protocol::SessionId>&, DriverClassT* driver,
        const base::Value* parameters, CommandResultHandler* result_handler)>
        RunCommandCallback;

    typedef base::Callback<util::CommandResult<R>(DriverClassT*)>
        DriverCommandFunction;
    // After binding the first argument, this function signature matches that of
    // RunCommandCallback.
    // The first argument is a base::Callback that runs a DriverClassT member
    // function with no parameters.
    static void RunCommand(
        const DriverCommandFunction& driver_command,
        const base::optional<protocol::SessionId>& session_id,
        DriverClassT* driver, const base::Value* parameters,
        CommandResultHandler* result_handler) {
      // Ignore parameters.
      int retries = 0;
      util::CommandResult<R> command_result;
      do {
        command_result = driver_command.Run(driver);
      } while (command_result.can_retry() && (retries++ < kMaxRetries));
      internal::ReturnResponse(session_id, command_result, result_handler);
    }

    // After binding the first argument, this function signature matches that of
    // RunCommandCallback.
    // The first argument is a base::Callback that runs a DriverClassT member
    // function with one parameter.
    template <typename A1>
    static void ExtractParameterAndRunCommand(
        const base::Callback<util::CommandResult<R>(
            DriverClassT*,
            typename base::internal::CallbackParamTraits<A1>::ForwardType)>&
            driver_command,
        const base::optional<protocol::SessionId>& session_id,
        DriverClassT* driver, const base::Value* parameters,
        CommandResultHandler* result_handler) {
      // Extract the parameter from |parameters|. If unsuccessful, return a
      // kInvalidParameters error. Otherwise, pass the extracted parameter to
      // the |driver_command|.
      base::optional<A1> param = internal::FromValue<A1>(parameters);
      if (!param) {
        result_handler->SendInvalidRequestResponse(
            WebDriverDispatcher::CommandResultHandler::kInvalidParameters, "");
      } else {
        int retries = 0;
        util::CommandResult<R> command_result;
        do {
          command_result = driver_command.Run(driver, param.value());
        } while (command_result.can_retry() && (retries++ < kMaxRetries));
        internal::ReturnResponse(session_id, command_result, result_handler);
      }
    }

    // Create a new CommandHandler instance, and base::Bind to its HandleCommand
    // function.
    static DispatchCommandCallback GetCommandHandler(
        const GetSessionCommand& get_session_command,
        const GetDriverCommand& get_driver_command,
        const RunCommandCallback& run_command_callback) {
      scoped_refptr<CommandHandler> command_handler(new CommandHandler(
          get_session_command, get_driver_command, run_command_callback));
      return base::Bind(&CommandHandler::HandleCommand, command_handler);
    }

   private:
    // Simple constructor that sets each of the necessary callbacks.
    CommandHandler(const GetSessionCommand& get_session_callback,
                   const GetDriverCommand& get_driver_callback,
                   const RunCommandCallback& run_command_callback)
        : get_session_(get_session_callback),
          get_driver_(get_driver_callback),
          run_command_(run_command_callback) {}

    // This function matches the WebDriverDispatcher::DispatchCommandCallback
    // signature, and as such is appropriate to be passed to the
    // WebDriverDispatcher::RegisterCommand function.
    // Using the the callbacks stored in this CommandHandler, it will extract
    // the appropriate XXXDriver, and execute |run_command_| on it.
    void HandleCommand(const base::Value* value,
                       const PathVariableMap* path_variables,
                       scoped_ptr<CommandResultHandler> result_handler) {
      SessionDriver* session =
          get_session_.Run(path_variables, result_handler.get());
      if (session) {
        DriverClassT* driver =
            get_driver_.Run(session, path_variables, result_handler.get());
        if (driver) {
          run_command_.Run(session->session_id(), driver, value,
                           result_handler.get());
        }
      }
    }

    GetSessionCommand get_session_;
    GetDriverCommand get_driver_;
    RunCommandCallback run_command_;
  };

  GetSessionCommand get_session_;
  GetDriverCommand get_driver_;
};

}  // namespace util
}  // namespace webdriver
}  // namespace cobalt

#endif  // COBALT_WEBDRIVER_UTIL_DISPATCH_COMMAND_FACTORY_H_
