/*
 * 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_WINDOW_DRIVER_H_
#define COBALT_WEBDRIVER_WINDOW_DRIVER_H_

#if defined(ENABLE_WEBDRIVER)

#include <string>
#include <vector>

#include "base/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/stl_util.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "cobalt/dom/keyboard_event.h"
#include "cobalt/dom/window.h"
#include "cobalt/webdriver/element_driver.h"
#include "cobalt/webdriver/element_mapping.h"
#include "cobalt/webdriver/keyboard.h"
#include "cobalt/webdriver/protocol/cookie.h"
#include "cobalt/webdriver/protocol/frame_id.h"
#include "cobalt/webdriver/protocol/keys.h"
#include "cobalt/webdriver/protocol/script.h"
#include "cobalt/webdriver/protocol/search_strategy.h"
#include "cobalt/webdriver/protocol/size.h"
#include "cobalt/webdriver/protocol/window_id.h"
#include "cobalt/webdriver/script_executor.h"
#include "cobalt/webdriver/util/call_on_message_loop.h"
#include "cobalt/webdriver/util/command_result.h"

namespace cobalt {
namespace webdriver {

// A WebDriver windowHandle will map to a WindowDriver instance.
// WebDriver commands that interact with a Window, such as:
//     /session/:sessionId/window/:windowHandle/size
// will map to a method on this class.
class WindowDriver : private ElementMapping {
 public:
  typedef base::Callback<void(scoped_refptr<dom::Element>,
                              const dom::KeyboardEvent::Data&)>
      KeyboardEventInjector;
  typedef base::Callback<scoped_refptr<script::GlobalEnvironment>()>
      GetGlobalEnvironmentFunction;
  WindowDriver(const protocol::WindowId& window_id,
               const base::WeakPtr<dom::Window>& window,
               const GetGlobalEnvironmentFunction& get_global_environment,
               KeyboardEventInjector keyboard_injector,
               const scoped_refptr<base::MessageLoopProxy>& message_loop);
  ~WindowDriver();
  const protocol::WindowId& window_id() { return window_id_; }
  ElementDriver* GetElementDriver(const protocol::ElementId& element_id);

  util::CommandResult<protocol::Size> GetWindowSize();
  util::CommandResult<void> Navigate(const GURL& url);
  util::CommandResult<std::string> GetCurrentUrl();
  util::CommandResult<std::string> GetTitle();
  util::CommandResult<protocol::ElementId> FindElement(
      const protocol::SearchStrategy& strategy);
  util::CommandResult<std::vector<protocol::ElementId> > FindElements(
      const protocol::SearchStrategy& strategy);
  // Note: The source may be a fairly large string that is being copied around
  // by value here.
  util::CommandResult<std::string> GetSource();
  util::CommandResult<protocol::ScriptResult> Execute(
      const protocol::Script& script);
  util::CommandResult<protocol::ScriptResult> ExecuteAsync(
      const protocol::Script& script);
  util::CommandResult<void> SendKeys(const protocol::Keys& keys);
  util::CommandResult<protocol::ElementId> GetActiveElement();
  util::CommandResult<void> SwitchFrame(const protocol::FrameId& frame_id);
  util::CommandResult<std::vector<protocol::Cookie> > GetAllCookies();
  util::CommandResult<std::vector<protocol::Cookie> > GetCookie(
      const std::string& name);
  util::CommandResult<void> AddCookie(const protocol::Cookie& cookie);

 private:
  typedef base::hash_map<std::string, ElementDriver*> ElementDriverMap;
  typedef ElementDriverMap::iterator ElementDriverMapIt;
  typedef std::vector<protocol::ElementId> ElementIdVector;

  // ScriptExecutor::ElementMapping implementation.
  protocol::ElementId ElementToId(
      const scoped_refptr<dom::Element>& element) OVERRIDE;
  scoped_refptr<dom::Element> IdToElement(
      const protocol::ElementId& id) OVERRIDE;

  dom::Window* GetWeak() {
    DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
    return window_.get();
  }

  // Create a new ElementDriver that wraps this weak_element and return the
  // ElementId that maps to the new ElementDriver.
  protocol::ElementId CreateNewElementDriver(
      const base::WeakPtr<dom::Element>& weak_element);

  // Shared logic between FindElement and FindElements.
  template <typename T>
  util::CommandResult<T> FindElementsInternal(
      const protocol::SearchStrategy& strategy);

  util::CommandResult<protocol::ScriptResult> ExecuteScriptInternal(
      const protocol::Script& script,
      base::optional<base::TimeDelta> async_timeout,
      ScriptExecutorResult::ResultHandler* result_handler);

  util::CommandResult<void> SendKeysInternal(
      scoped_ptr<Keyboard::KeyboardEventVector> keyboard_events);

  util::CommandResult<void> NavigateInternal(const GURL& url);

  util::CommandResult<void> AddCookieInternal(const protocol::Cookie& cookie);

  util::CommandResult<protocol::ElementId> GetActiveElementInternal();

  const protocol::WindowId window_id_;

  // Bound to the WebDriver thread.
  base::ThreadChecker thread_checker_;

  KeyboardEventInjector keyboard_injector_;

  // Anything that interacts with the window must be run on this message loop.
  scoped_refptr<base::MessageLoopProxy> window_message_loop_;

  // Weak handle to the dom::Window that must only be accessed from
  // |window_message_loop|
  base::WeakPtr<dom::Window> window_;

  // This must only be accessed from |window_message_loop_|.
  GetGlobalEnvironmentFunction get_global_environment_;

  // Helper object for commands that execute script. This must only be accessed
  // from the |window_message_loop_|.
  base::WeakPtr<ScriptExecutor> script_executor_;

  // Mapping of protocol::ElementId to ElementDriver*. This should only be
  // accessed from the |window_message_loop_|, though it will be destructed
  // from the WebDriver thread.
  ElementDriverMap element_drivers_;

  // Ensure ElementDrivers that this WindowDriver owns are deleted on
  // destruction of the WindowDriver.
  STLValueDeleter<ElementDriverMap> element_driver_map_deleter_;

  // Monotonically increasing number to provide unique element ids.
  int32 next_element_id_;
};

}  // namespace webdriver
}  // namespace cobalt

#endif  // defined(ENABLE_WEBDRIVER)
#endif  // COBALT_WEBDRIVER_WINDOW_DRIVER_H_
