/*
 * 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<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);

  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_
