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

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