// 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_WEB_DRIVER_MODULE_H_
#define COBALT_WEBDRIVER_WEB_DRIVER_MODULE_H_

#include <memory>
#include <string>

#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/threading/thread_checker.h"
#include "cobalt/dom/window.h"
#include "cobalt/webdriver/dispatcher.h"
#include "cobalt/webdriver/protocol/button.h"
#include "cobalt/webdriver/protocol/capabilities.h"
#include "cobalt/webdriver/protocol/element_id.h"
#include "cobalt/webdriver/protocol/moveto.h"
#include "cobalt/webdriver/protocol/server_status.h"
#include "cobalt/webdriver/protocol/session_id.h"
#include "cobalt/webdriver/protocol/window_id.h"
#include "cobalt/webdriver/screencast/screencast_module.h"
#include "cobalt/webdriver/screenshot.h"
#include "cobalt/webdriver/util/command_result.h"

namespace cobalt {
namespace webdriver {

class ElementDriver;
class SessionDriver;
class WebDriverServer;
class WindowDriver;

class WebDriverModule {
 public:
  typedef base::Callback<std::unique_ptr<SessionDriver>(
      const protocol::SessionId&)>
      CreateSessionDriverCB;
  typedef Screenshot::GetScreenshotFunction GetScreenshotFunction;
  typedef base::Callback<void(const std::string&)> SetProxyFunction;
  // Use this as the default listen_ip. It means "any interface on the local
  // machine" eg INADDR_ANY.
  static const char kDefaultListenIp[];
  WebDriverModule(int server_port, const std::string& listen_ip,
                  const CreateSessionDriverCB& create_session_driver_cb,
                  const GetScreenshotFunction& get_screenshot_function,
                  const SetProxyFunction& set_proxy_function,
                  const base::Closure& shutdown_cb);
  ~WebDriverModule();

  // This will be called when the WebModule, which owns the Window object in the
  // WindowDriver, is destroyed and recreated in response to navigation. This
  // unfortunately does leave a window where a WebDriver command may be run
  // before RefreshWindowDriver has been called. In this case, the weak Window
  // reference will be invalidated and the WebDriver command will fail. This is
  // a side-effect of Cobalt destroying and re-creating a Window on navigation,
  // rather than the navigation occurring in place.
  void OnWindowRecreated();

 private:
  void StartServer(int server_port, const std::string& listen_ip);
  void StopServerAndSession();
  void GetServerStatus(
      const base::Value* parameters,
      const WebDriverDispatcher::PathVariableMap* path_variables,
      std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
          result_handler);
  void GetActiveSessions(
      const base::Value* parameters,
      const WebDriverDispatcher::PathVariableMap* path_variables,
      std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
          result_handler);
  void CreateSession(const base::Value* parameters,
                     const WebDriverDispatcher::PathVariableMap* path_variables,
                     std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
                         result_handler);
  void DeleteSession(const base::Value* parameters,
                     const WebDriverDispatcher::PathVariableMap* path_variables,
                     std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
                         result_handler);
  // This method starts a Screencast server on port 3003 for a client to connect
  // to. This is not standard Webdriver functionality.
  void StartScreencast(
      const base::Value* parameters,
      const WebDriverDispatcher::PathVariableMap* path_variables,
      std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
          result_handler);
  // This method destroys the Screencast server.
  // This is not standard Webdriver functionality.
  void StopScreencast(
      const base::Value* parameters,
      const WebDriverDispatcher::PathVariableMap* path_variables,
      std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
          result_handler);
  void RequestScreenshot(
      const base::Value* parameters,
      const WebDriverDispatcher::PathVariableMap* path_variables,
      std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
          result_handler);
  void Shutdown(const base::Value* parameters,
                const WebDriverDispatcher::PathVariableMap* path_variables,
                std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
                    result_handler);

  void ElementEquals(const base::Value* parameters,
                     const WebDriverDispatcher::PathVariableMap* path_variables,
                     std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
                         result_handler);
  void GetAttribute(const base::Value* parameters,
                    const WebDriverDispatcher::PathVariableMap* path_variables,
                    std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
                        result_handler);
  void GetCssProperty(
      const base::Value* parameters,
      const WebDriverDispatcher::PathVariableMap* path_variables,
      std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
          result_handler);
  void RequestElementScreenshot(
      const base::Value* parameters,
      const WebDriverDispatcher::PathVariableMap* path_variables,
      std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
          result_handler);
  void GetCookieByName(
      const base::Value* parameters,
      const WebDriverDispatcher::PathVariableMap* path_variables,
      std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
          result_handler);

  void IgnoreCommand(const base::Value* parameters,
                     const WebDriverDispatcher::PathVariableMap* path_variables,
                     std::unique_ptr<WebDriverDispatcher::CommandResultHandler>
                         result_handler);

  SessionDriver* GetSessionDriver(const protocol::SessionId& session_id);

  util::CommandResult<protocol::Capabilities> CreateSessionInternal(
      const protocol::RequestedCapabilities& capabilities);

  THREAD_CHECKER(thread_checker_);

  // All WebDriver operations including HTTP server will occur on this thread.
  base::Thread webdriver_thread_;

  // Create a new WebDriver session through this callback.
  CreateSessionDriverCB create_session_driver_cb_;

  // Request a screenshot to be created and written to a file.
  GetScreenshotFunction get_screenshot_function_;

  // Configure custom proxy settings.
  SetProxyFunction set_proxy_function_;

  // Callback to shut down the application.
  base::Closure shutdown_cb_;

  // The WebDriver command dispatcher
  std::unique_ptr<WebDriverDispatcher> webdriver_dispatcher_;

  // The WebDriver server
  std::unique_ptr<WebDriverServer> webdriver_server_;

  // The current (and only) WebDriver session, if it has been created.
  std::unique_ptr<SessionDriver> session_;

  // The WebDriver server status.
  const protocol::ServerStatus status_;

  base::Callback<SessionDriver*(const protocol::SessionId&)>
      get_session_driver_;

  std::unique_ptr<screencast::ScreencastModule> screencast_driver_module_;
};

}  // namespace webdriver
}  // namespace cobalt

#endif  // COBALT_WEBDRIVER_WEB_DRIVER_MODULE_H_
