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

#include "cobalt/webdriver/window_driver.h"

#include <utility>

#include "base/synchronization/waitable_event.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/location.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/webdriver/keyboard.h"
#include "cobalt/webdriver/search.h"
#include "cobalt/webdriver/util/call_on_message_loop.h"

namespace cobalt {
namespace webdriver {
namespace {

class SyncExecuteResultHandler : public ScriptExecutorResult::ResultHandler {
 public:
  void OnResult(const std::string& result) OVERRIDE {
    DCHECK(!result_);
    result_ = result;
  }
  void OnTimeout() OVERRIDE { NOTREACHED(); }
  std::string result() const {
    DCHECK(result_);
    return result_.value_or(std::string());
  }

 private:
  base::optional<std::string> result_;
};

class AsyncExecuteResultHandler : public ScriptExecutorResult::ResultHandler {
 public:
  AsyncExecuteResultHandler() : timed_out_(false), event_(true, false) {}

  void WaitForResult() { event_.Wait(); }
  bool timed_out() const { return timed_out_; }
  const std::string& result() const { return result_; }

 private:
  void OnResult(const std::string& result) OVERRIDE {
    result_ = result;
    event_.Signal();
  }
  void OnTimeout() OVERRIDE {
    timed_out_ = true;
    event_.Signal();
  }

  std::string result_;
  bool timed_out_;
  base::WaitableEvent event_;
};

std::string GetCurrentUrl(dom::Window* window) {
  DCHECK(window);
  DCHECK(window->location());
  return window->location()->href();
}

std::string GetTitle(dom::Window* window) {
  DCHECK(window);
  DCHECK(window->document());
  return window->document()->title();
}

protocol::Size GetWindowSize(dom::Window* window) {
  DCHECK(window);
  float width = window->outer_width();
  float height = window->outer_height();
  return protocol::Size(width, height);
}

std::string GetSource(dom::Window* window) {
  DCHECK(window);
  DCHECK(window->document());
  DCHECK(window->document()->document_element());
  return window->document()->document_element()->outer_html(NULL);
}

std::vector<protocol::Cookie> GetAllCookies(dom::Window* window) {
  DCHECK(window);
  DCHECK(window->document());
  std::string cookies_string = window->document()->cookie();
  std::vector<protocol::Cookie> cookies;
  protocol::Cookie::ToCookieVector(cookies_string, &cookies);
  return cookies;
}

}  // namespace

WindowDriver::WindowDriver(
    const protocol::WindowId& window_id,
    const base::WeakPtr<dom::Window>& window,
    const GetGlobalEnvironmentFunction& get_global_environment_function,
    KeyboardEventInjector keyboard_injector,
    const scoped_refptr<base::MessageLoopProxy>& message_loop)
    : window_id_(window_id),
      window_(window),
      get_global_environment_(get_global_environment_function),
      keyboard_injector_(keyboard_injector),
      window_message_loop_(message_loop),
      element_driver_map_deleter_(&element_drivers_),
      next_element_id_(0) {
  // The WindowDriver may have been created on some arbitrary thread (i.e. the
  // thread that owns the Window). Detach the thread checker so it can be
  // re-bound to the next thread that calls a webdriver API, which should be
  // the WebDriver thread.
  thread_checker_.DetachFromThread();
}

WindowDriver::~WindowDriver() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

ElementDriver* WindowDriver::GetElementDriver(
    const protocol::ElementId& element_id) {
  if (base::MessageLoopProxy::current() != window_message_loop_) {
    // It's expected that the WebDriver thread is the only other thread to call
    // this function.
    DCHECK(thread_checker_.CalledOnValidThread());
    ElementDriver* result;
    bool success = util::TryCallOnMessageLoop(
        window_message_loop_, base::Bind(&WindowDriver::GetElementDriver,
                                         base::Unretained(this), element_id),
        &result);
    return success ? result : NULL;
  }
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  ElementDriverMap::iterator it = element_drivers_.find(element_id.id());
  if (it != element_drivers_.end()) {
    return it->second;
  }
  return NULL;
}

util::CommandResult<protocol::Size> WindowDriver::GetWindowSize() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_message_loop_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetWindowSize),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<void> WindowDriver::Navigate(const GURL& url) {
  DCHECK(thread_checker_.CalledOnValidThread());
  return util::CallOnMessageLoop(
      window_message_loop_,
      base::Bind(&WindowDriver::NavigateInternal, base::Unretained(this), url),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<std::string> WindowDriver::GetCurrentUrl() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_message_loop_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetCurrentUrl),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<std::string> WindowDriver::GetTitle() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_message_loop_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetTitle),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<protocol::ElementId> WindowDriver::FindElement(
    const protocol::SearchStrategy& strategy) {
  DCHECK(thread_checker_.CalledOnValidThread());

  return util::CallOnMessageLoop(
      window_message_loop_,
      base::Bind(&WindowDriver::FindElementsInternal<protocol::ElementId>,
                 base::Unretained(this), strategy),
      protocol::Response::kNoSuchElement);
}

util::CommandResult<std::vector<protocol::ElementId> >
WindowDriver::FindElements(const protocol::SearchStrategy& strategy) {
  DCHECK(thread_checker_.CalledOnValidThread());
  return util::CallOnMessageLoop(
      window_message_loop_,
      base::Bind(&WindowDriver::FindElementsInternal<ElementIdVector>,
                 base::Unretained(this), strategy),
      protocol::Response::kNoSuchElement);
}

util::CommandResult<std::string> WindowDriver::GetSource() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_message_loop_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetSource),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<protocol::ScriptResult> WindowDriver::Execute(
    const protocol::Script& script) {
  typedef util::CommandResult<protocol::ScriptResult> CommandResult;
  DCHECK(thread_checker_.CalledOnValidThread());
  // Pre-load the ScriptExecutor source so we don't hit the disk on
  // window_message_loop_.
  ScriptExecutor::LoadExecutorSourceCode();

  SyncExecuteResultHandler result_handler;

  CommandResult result = util::CallOnMessageLoop(
      window_message_loop_,
      base::Bind(&WindowDriver::ExecuteScriptInternal, base::Unretained(this),
                 script, base::nullopt, &result_handler),
      protocol::Response::kNoSuchWindow);
  if (result.is_success()) {
    return CommandResult(protocol::ScriptResult(result_handler.result()));
  } else {
    return result;
  }
}

util::CommandResult<protocol::ScriptResult> WindowDriver::ExecuteAsync(
    const protocol::Script& script) {
  typedef util::CommandResult<protocol::ScriptResult> CommandResult;
  DCHECK(thread_checker_.CalledOnValidThread());
  // Pre-load the ScriptExecutor source so we don't hit the disk on
  // window_message_loop_.
  ScriptExecutor::LoadExecutorSourceCode();

  const base::TimeDelta kDefaultAsyncTimeout =
      base::TimeDelta::FromMilliseconds(0);
  AsyncExecuteResultHandler result_handler;
  CommandResult result = util::CallOnMessageLoop(
      window_message_loop_,
      base::Bind(&WindowDriver::ExecuteScriptInternal, base::Unretained(this),
                 script, kDefaultAsyncTimeout, &result_handler),
      protocol::Response::kNoSuchWindow);

  if (!result.is_success()) {
    return result;
  }

  result_handler.WaitForResult();
  if (result_handler.timed_out()) {
    return CommandResult(protocol::Response::kTimeOut);
  } else {
    return CommandResult(protocol::ScriptResult(result_handler.result()));
  }
}

util::CommandResult<void> WindowDriver::SendKeys(const protocol::Keys& keys) {
  // Translate the keys into KeyboardEvents. Don't reset modifiers.
  scoped_ptr<Keyboard::KeyboardEventVector> events(
      new Keyboard::KeyboardEventVector());
  Keyboard::TranslateToKeyEvents(keys.utf8_keys(), Keyboard::kKeepModifiers,
                                 events.get());
  // Dispatch the keyboard events.
  return util::CallOnMessageLoop(
      window_message_loop_,
      base::Bind(&WindowDriver::SendKeysInternal, base::Unretained(this),
                 base::Passed(&events)),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<protocol::ElementId> WindowDriver::GetActiveElement() {
  return util::CallOnMessageLoop(
      window_message_loop_, base::Bind(&WindowDriver::GetActiveElementInternal,
                                       base::Unretained(this)),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<void> WindowDriver::SwitchFrame(
    const protocol::FrameId& frame_id) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Cobalt doesn't support frames, but if a WebDriver client requests to
  // switch to the top-level browsing context, trivially return success.
  if (frame_id.is_top_level_browsing_context()) {
    return util::CommandResult<void>(protocol::Response::kSuccess);
  } else {
    return util::CommandResult<void>(protocol::Response::kNoSuchFrame);
  }
}

util::CommandResult<std::vector<protocol::Cookie> >
WindowDriver::GetAllCookies() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_message_loop_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetAllCookies),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<std::vector<protocol::Cookie> > WindowDriver::GetCookie(
    const std::string& name) {
  typedef util::CommandResult<std::vector<protocol::Cookie> > CommandResult;
  CommandResult command_result = GetAllCookies();
  if (command_result.is_success()) {
    std::vector<protocol::Cookie> filtered_cookies;
    for (size_t i = 0; i < command_result.result().size(); ++i) {
      if (command_result.result()[i].name() == name) {
        filtered_cookies.push_back(command_result.result()[i]);
        break;
      }
    }
    command_result = CommandResult(filtered_cookies);
  }
  return command_result;
}

util::CommandResult<void> WindowDriver::AddCookie(
    const protocol::Cookie& cookie) {
  DCHECK(thread_checker_.CalledOnValidThread());
  return util::CallOnMessageLoop(window_message_loop_,
                                 base::Bind(&WindowDriver::AddCookieInternal,
                                            base::Unretained(this), cookie),
                                 protocol::Response::kNoSuchWindow);
}

protocol::ElementId WindowDriver::ElementToId(
    const scoped_refptr<dom::Element>& element) {
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  return CreateNewElementDriver(base::AsWeakPtr(element.get()));
}

scoped_refptr<dom::Element> WindowDriver::IdToElement(
    const protocol::ElementId& id) {
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  return make_scoped_refptr(GetElementDriver(id)->GetWeakElement());
}

protocol::ElementId WindowDriver::CreateNewElementDriver(
    const base::WeakPtr<dom::Element>& weak_element) {
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);

  protocol::ElementId element_id(
      base::StringPrintf("element-%d", next_element_id_++));
  std::pair<ElementDriverMapIt, bool> pair_it =
      element_drivers_.insert(std::make_pair(
          element_id.id(), new ElementDriver(element_id, weak_element, this,
                                             keyboard_injector_,
                                             window_message_loop_)));
  DCHECK(pair_it.second)
      << "An ElementDriver was already mapped to the element id: "
      << element_id.id();
  return element_id;
}

// Internal logic for FindElement and FindElements that must be run on the
// Window's message loop.
template <typename T>
util::CommandResult<T> WindowDriver::FindElementsInternal(
    const protocol::SearchStrategy& strategy) {
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  typedef util::CommandResult<T> CommandResult;
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }
  return Search::FindElementsUnderNode<T>(strategy, window_->document().get(),
                                          this);
}

util::CommandResult<protocol::ScriptResult> WindowDriver::ExecuteScriptInternal(
    const protocol::Script& script,
    base::optional<base::TimeDelta> async_timeout,
    ScriptExecutorResult::ResultHandler* async_handler) {
  typedef util::CommandResult<protocol::ScriptResult> CommandResult;
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

  scoped_refptr<script::GlobalEnvironment> global_environment =
      get_global_environment_.Run();
  DCHECK(global_environment);

  // Lazily initialize this the first time we need to run a script. It must be
  // initialized on window_message_loop_. It can persist across multiple calls
  // to execute script, but must be destroyed along with the associated
  // global object, thus with the WindowDriver.
  if (!script_executor_) {
    scoped_refptr<ScriptExecutor> script_executor =
        ScriptExecutor::Create(this, global_environment);
    if (!script_executor) {
      DLOG(INFO) << "Failed to create ScriptExecutor.";
      return CommandResult(protocol::Response::kUnknownError);
    }
    script_executor_ = base::AsWeakPtr(script_executor.get());
  }

  DLOG(INFO) << "Executing: " << script.function_body();
  DLOG(INFO) << "Arguments: " << script.argument_array();

  scoped_refptr<ScriptExecutorParams> params =
      ScriptExecutorParams::Create(global_environment, script.function_body(),
                                   script.argument_array(), async_timeout);

  if (params->function_object()) {
    if (script_executor_->Execute(params, async_handler)) {
      return CommandResult(protocol::Response::kSuccess);
    }
  }
  return CommandResult(protocol::Response::kJavaScriptError);
}

util::CommandResult<void> WindowDriver::SendKeysInternal(
    scoped_ptr<Keyboard::KeyboardEventVector> events) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

  for (size_t i = 0; i < events->size(); ++i) {
    keyboard_injector_.Run(scoped_refptr<dom::Element>(), (*events)[i]);
  }
  return CommandResult(protocol::Response::kSuccess);
}

util::CommandResult<void> WindowDriver::NavigateInternal(const GURL& url) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }
  window_->location()->Replace(url.spec());
  return CommandResult(protocol::Response::kSuccess);
}

util::CommandResult<void> WindowDriver::AddCookieInternal(
    const protocol::Cookie& cookie) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }
  // If the domain was set, ensure that it is valid with respect to the
  // the document's domain.
  std::string document_domain = window_->document()->location()->host();

  if (cookie.domain()) {
    // This is the same way the domain is checked in FirefoxDriver.
    if (document_domain.find(cookie.domain().value()) == std::string::npos) {
      return CommandResult(protocol::Response::kInvalidCookieDomain);
    }
  }

  std::string cookie_string = cookie.ToCookieString(document_domain);
  window_->document()->set_cookie(cookie_string);
  return CommandResult(protocol::Response::kSuccess);
}

util::CommandResult<protocol::ElementId>
WindowDriver::GetActiveElementInternal() {
  typedef util::CommandResult<protocol::ElementId> CommandResult;
  DCHECK_EQ(base::MessageLoopProxy::current(), window_message_loop_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }
  scoped_refptr<dom::Element> active = window_->document()->active_element();
  if (active) {
    return CommandResult(ElementToId(active));
  } else {
    return CommandResult(protocol::Response::kUnknownError);
  }
}

}  // namespace webdriver
}  // namespace cobalt
