// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/chromedriver/element_util.h"

#include <utility>

#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/test/chromedriver/basic_types.h"
#include "chrome/test/chromedriver/chrome/chrome.h"
#include "chrome/test/chromedriver/chrome/js.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/web_view.h"
#include "chrome/test/chromedriver/session.h"
#include "third_party/webdriver/atoms.h"

namespace {

const char kElementKey[] = "ELEMENT";

bool ParseFromValue(base::Value* value, WebPoint* point) {
  base::DictionaryValue* dict_value;
  if (!value->GetAsDictionary(&dict_value))
    return false;
  double x = 0;
  double y = 0;
  if (!dict_value->GetDouble("x", &x) ||
      !dict_value->GetDouble("y", &y))
    return false;
  point->x = static_cast<int>(x);
  point->y = static_cast<int>(y);
  return true;
}

bool ParseFromValue(base::Value* value, WebSize* size) {
  base::DictionaryValue* dict_value;
  if (!value->GetAsDictionary(&dict_value))
    return false;
  double width = 0;
  double height = 0;
  if (!dict_value->GetDouble("width", &width) ||
      !dict_value->GetDouble("height", &height))
    return false;
  size->width = static_cast<int>(width);
  size->height = static_cast<int>(height);
  return true;
}

bool ParseFromValue(base::Value* value, WebRect* rect) {
  base::DictionaryValue* dict_value;
  if (!value->GetAsDictionary(&dict_value))
    return false;
  double x = 0;
  double y = 0;
  double width = 0;
  double height = 0;
  if (!dict_value->GetDouble("left", &x) ||
      !dict_value->GetDouble("top", &y) ||
      !dict_value->GetDouble("width", &width) ||
      !dict_value->GetDouble("height", &height))
    return false;
  rect->origin.x = static_cast<int>(x);
  rect->origin.y = static_cast<int>(y);
  rect->size.width = static_cast<int>(width);
  rect->size.height = static_cast<int>(height);
  return true;
}

std::unique_ptr<base::DictionaryValue> CreateValueFrom(const WebRect& rect) {
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
  dict->SetInteger("left", rect.X());
  dict->SetInteger("top", rect.Y());
  dict->SetInteger("width", rect.Width());
  dict->SetInteger("height", rect.Height());
  return dict;
}

Status CallAtomsJs(const std::string& frame,
                   WebView* web_view,
                   const char* const* atom_function,
                   const base::ListValue& args,
                   std::unique_ptr<base::Value>* result) {
  return web_view->CallFunction(
      frame, webdriver::atoms::asString(atom_function), args, result);
}

Status VerifyElementClickable(
    const std::string& frame,
    WebView* web_view,
    const std::string& element_id,
    const WebPoint& location) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  args.Append(CreateValueFrom(location));
  std::unique_ptr<base::Value> result;
  Status status = CallAtomsJs(
      frame, web_view, webdriver::atoms::IS_ELEMENT_CLICKABLE,
      args, &result);
  if (status.IsError())
    return status;
  base::DictionaryValue* dict;
  bool is_clickable = false;
  if (!result->GetAsDictionary(&dict) ||
      !dict->GetBoolean("clickable", &is_clickable)) {
    return Status(kUnknownError,
                  "failed to parse value of IS_ELEMENT_CLICKABLE");
  }

  if (!is_clickable) {
    std::string message;
    if (!dict->GetString("message", &message))
      message = "element is not clickable";
    return Status(kUnknownError, message);
  }
  return Status(kOk);
}

Status ScrollElementRegionIntoViewHelper(
    const std::string& frame,
    WebView* web_view,
    const std::string& element_id,
    const WebRect& region,
    bool center,
    const std::string& clickable_element_id,
    WebPoint* location) {
  WebPoint tmp_location = *location;
  base::ListValue args;
  args.Append(CreateElement(element_id));
  args.AppendBoolean(center);
  args.Append(CreateValueFrom(region));
  std::unique_ptr<base::Value> result;
  Status status = web_view->CallFunction(
      frame, webdriver::atoms::asString(webdriver::atoms::GET_LOCATION_IN_VIEW),
      args, &result);
  if (status.IsError())
    return status;
  if (!ParseFromValue(result.get(), &tmp_location)) {
    return Status(kUnknownError,
                  "failed to parse value of GET_LOCATION_IN_VIEW");
  }
  if (!clickable_element_id.empty()) {
    WebPoint middle = tmp_location;
    middle.Offset(region.Width() / 2, region.Height() / 2);
    status = VerifyElementClickable(
        frame, web_view, clickable_element_id, middle);
    if (status.IsError())
      return status;
  }
  *location = tmp_location;
  return Status(kOk);
}

Status GetElementEffectiveStyle(
    const std::string& frame,
    WebView* web_view,
    const std::string& element_id,
    const std::string& property,
    std::string* value) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  args.AppendString(property);
  std::unique_ptr<base::Value> result;
  Status status = web_view->CallFunction(
      frame, webdriver::atoms::asString(webdriver::atoms::GET_EFFECTIVE_STYLE),
      args, &result);
  if (status.IsError())
    return status;
  if (!result->GetAsString(value)) {
    return Status(kUnknownError,
                  "failed to parse value of GET_EFFECTIVE_STYLE");
  }
  return Status(kOk);
}

Status GetElementBorder(
    const std::string& frame,
    WebView* web_view,
    const std::string& element_id,
    int* border_left,
    int* border_top) {
  std::string border_left_str;
  Status status = GetElementEffectiveStyle(
      frame, web_view, element_id, "border-left-width", &border_left_str);
  if (status.IsError())
    return status;
  std::string border_top_str;
  status = GetElementEffectiveStyle(
      frame, web_view, element_id, "border-top-width", &border_top_str);
  if (status.IsError())
    return status;
  int border_left_tmp = -1;
  int border_top_tmp = -1;
  base::StringToInt(border_left_str, &border_left_tmp);
  base::StringToInt(border_top_str, &border_top_tmp);
  if (border_left_tmp == -1 || border_top_tmp == -1)
    return Status(kUnknownError, "failed to get border width of element");
  *border_left = border_left_tmp;
  *border_top = border_top_tmp;
  return Status(kOk);
}

}  // namespace

std::unique_ptr<base::DictionaryValue> CreateElement(
    const std::string& element_id) {
  std::unique_ptr<base::DictionaryValue> element(new base::DictionaryValue());
  element->SetString(kElementKey, element_id);
  return element;
}

std::unique_ptr<base::DictionaryValue> CreateValueFrom(const WebPoint& point) {
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
  dict->SetInteger("x", point.x);
  dict->SetInteger("y", point.y);
  return dict;
}

Status FindElement(int interval_ms,
                   bool only_one,
                   const std::string* root_element_id,
                   Session* session,
                   WebView* web_view,
                   const base::DictionaryValue& params,
                   std::unique_ptr<base::Value>* value) {
  std::string strategy;
  if (!params.GetString("using", &strategy))
    return Status(kUnknownError, "'using' must be a string");
  std::string target;
  if (!params.GetString("value", &target))
    return Status(kUnknownError, "'value' must be a string");

  std::string script;
  if (only_one)
    script = webdriver::atoms::asString(webdriver::atoms::FIND_ELEMENT);
  else
    script = webdriver::atoms::asString(webdriver::atoms::FIND_ELEMENTS);
  std::unique_ptr<base::DictionaryValue> locator(new base::DictionaryValue());
  locator->SetString(strategy, target);
  base::ListValue arguments;
  arguments.Append(std::move(locator));
  if (root_element_id)
    arguments.Append(CreateElement(*root_element_id));

  base::TimeTicks start_time = base::TimeTicks::Now();
  while (true) {
    std::unique_ptr<base::Value> temp;
    Status status = web_view->CallFunction(
        session->GetCurrentFrameId(), script, arguments, &temp);
    if (status.IsError())
      return status;

    if (!temp->IsType(base::Value::TYPE_NULL)) {
      if (only_one) {
        value->reset(temp.release());
        return Status(kOk);
      } else {
        base::ListValue* result;
        if (!temp->GetAsList(&result))
          return Status(kUnknownError, "script returns unexpected result");

        if (result->GetSize() > 0U) {
          value->reset(temp.release());
          return Status(kOk);
        }
      }
    }

    if (base::TimeTicks::Now() - start_time >= session->implicit_wait) {
      if (only_one) {
        return Status(kNoSuchElement, "Unable to locate element: {\"method\":\""
         + strategy + "\",\"selector\":\"" + target + "\"}");
      } else {
        value->reset(new base::ListValue());
        return Status(kOk);
      }
    }
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(interval_ms));
  }

  return Status(kUnknownError);
}

Status GetActiveElement(Session* session,
                        WebView* web_view,
                        std::unique_ptr<base::Value>* value) {
  base::ListValue args;
  return web_view->CallFunction(
      session->GetCurrentFrameId(),
      "function() { return document.activeElement || document.body }",
      args,
      value);
}

Status IsElementFocused(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    bool* is_focused) {
  std::unique_ptr<base::Value> result;
  Status status = GetActiveElement(session, web_view, &result);
  if (status.IsError())
    return status;
  std::unique_ptr<base::Value> element_dict(CreateElement(element_id));
  *is_focused = result->Equals(element_dict.get());
  return Status(kOk);
}

Status GetElementAttribute(Session* session,
                           WebView* web_view,
                           const std::string& element_id,
                           const std::string& attribute_name,
                           std::unique_ptr<base::Value>* value) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  args.AppendString(attribute_name);
  return CallAtomsJs(
      session->GetCurrentFrameId(), web_view, webdriver::atoms::GET_ATTRIBUTE,
      args, value);
}

Status IsElementAttributeEqualToIgnoreCase(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    const std::string& attribute_name,
    const std::string& attribute_value,
    bool* is_equal) {
  std::unique_ptr<base::Value> result;
  Status status = GetElementAttribute(
      session, web_view, element_id, attribute_name, &result);
  if (status.IsError())
    return status;
  std::string actual_value;
  if (result->GetAsString(&actual_value)) {
    *is_equal =
        base::LowerCaseEqualsASCII(actual_value, attribute_value.c_str());
  } else {
    *is_equal = false;
  }
  return status;
}

Status GetElementClickableLocation(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    WebPoint* location) {
  std::string tag_name;
  Status status = GetElementTagName(session, web_view, element_id, &tag_name);
  if (status.IsError())
    return status;
  std::string target_element_id = element_id;
  if (tag_name == "area") {
    // Scroll the image into view instead of the area.
    const char kGetImageElementForArea[] =
        "function (element) {"
        "  var map = element.parentElement;"
        "  if (map.tagName.toLowerCase() != 'map')"
        "    throw new Error('the area is not within a map');"
        "  var mapName = map.getAttribute('name');"
        "  if (mapName == null)"
        "    throw new Error ('area\\'s parent map must have a name');"
        "  mapName = '#' + mapName.toLowerCase();"
        "  var images = document.getElementsByTagName('img');"
        "  for (var i = 0; i < images.length; i++) {"
        "    if (images[i].useMap.toLowerCase() == mapName)"
        "      return images[i];"
        "  }"
        "  throw new Error('no img is found for the area');"
        "}";
    base::ListValue args;
    args.Append(CreateElement(element_id));
    std::unique_ptr<base::Value> result;
    status = web_view->CallFunction(
        session->GetCurrentFrameId(), kGetImageElementForArea, args, &result);
    if (status.IsError())
      return status;
    const base::DictionaryValue* element_dict;
    if (!result->GetAsDictionary(&element_dict) ||
        !element_dict->GetString(kElementKey, &target_element_id))
      return Status(kUnknownError, "no element reference returned by script");
  }
  bool is_displayed = false;
  status = IsElementDisplayed(
      session, web_view, target_element_id, true, &is_displayed);
  if (status.IsError())
    return status;
  if (!is_displayed)
    return Status(kElementNotVisible);

  WebRect rect;
  status = GetElementRegion(session, web_view, element_id, &rect);
  if (status.IsError())
    return status;

  status = ScrollElementRegionIntoView(
      session, web_view, target_element_id, rect,
      true /* center */, element_id, location);
  if (status.IsError())
    return status;
  location->Offset(rect.Width() / 2, rect.Height() / 2);
  return Status(kOk);
}

Status GetElementEffectiveStyle(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    const std::string& property_name,
    std::string* property_value) {
  return GetElementEffectiveStyle(session->GetCurrentFrameId(), web_view,
                                  element_id, property_name, property_value);
}

Status GetElementRegion(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    WebRect* rect) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  std::unique_ptr<base::Value> result;
  Status status = web_view->CallFunction(
      session->GetCurrentFrameId(), kGetElementRegionScript, args, &result);
  if (status.IsError())
    return status;
  if (!ParseFromValue(result.get(), rect)) {
    return Status(kUnknownError,
                  "failed to parse value of getElementRegion");
  }
  return Status(kOk);
}

Status GetElementTagName(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    std::string* name) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  std::unique_ptr<base::Value> result;
  Status status = web_view->CallFunction(
      session->GetCurrentFrameId(),
      "function(elem) { return elem.tagName.toLowerCase(); }",
      args, &result);
  if (status.IsError())
    return status;
  if (!result->GetAsString(name))
    return Status(kUnknownError, "failed to get element tag name");
  return Status(kOk);
}

Status GetElementSize(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    WebSize* size) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  std::unique_ptr<base::Value> result;
  Status status = CallAtomsJs(
      session->GetCurrentFrameId(), web_view, webdriver::atoms::GET_SIZE,
      args, &result);
  if (status.IsError())
    return status;
  if (!ParseFromValue(result.get(), size))
    return Status(kUnknownError, "failed to parse value of GET_SIZE");
  return Status(kOk);
}

Status IsElementDisplayed(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    bool ignore_opacity,
    bool* is_displayed) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  args.AppendBoolean(ignore_opacity);
  std::unique_ptr<base::Value> result;
  Status status = CallAtomsJs(
      session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_DISPLAYED,
      args, &result);
  if (status.IsError())
    return status;
  if (!result->GetAsBoolean(is_displayed))
    return Status(kUnknownError, "IS_DISPLAYED should return a boolean value");
  return Status(kOk);
}

Status IsElementEnabled(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    bool* is_enabled) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  std::unique_ptr<base::Value> result;
  Status status = CallAtomsJs(
      session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_ENABLED,
      args, &result);
  if (status.IsError())
    return status;
  if (!result->GetAsBoolean(is_enabled))
    return Status(kUnknownError, "IS_ENABLED should return a boolean value");
  return Status(kOk);
}

Status IsOptionElementSelected(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    bool* is_selected) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  std::unique_ptr<base::Value> result;
  Status status = CallAtomsJs(
      session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_SELECTED,
      args, &result);
  if (status.IsError())
    return status;
  if (!result->GetAsBoolean(is_selected))
    return Status(kUnknownError, "IS_SELECTED should return a boolean value");
  return Status(kOk);
}

Status IsOptionElementTogglable(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    bool* is_togglable) {
  base::ListValue args;
  args.Append(CreateElement(element_id));
  std::unique_ptr<base::Value> result;
  Status status = web_view->CallFunction(
      session->GetCurrentFrameId(), kIsOptionElementToggleableScript,
      args, &result);
  if (status.IsError())
    return status;
  if (!result->GetAsBoolean(is_togglable))
    return Status(kUnknownError, "failed check if option togglable or not");
  return Status(kOk);
}

Status SetOptionElementSelected(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    bool selected) {
  // TODO(171034): need to fix throwing error if an alert is triggered.
  base::ListValue args;
  args.Append(CreateElement(element_id));
  args.AppendBoolean(selected);
  std::unique_ptr<base::Value> result;
  return CallAtomsJs(
      session->GetCurrentFrameId(), web_view, webdriver::atoms::CLICK,
      args, &result);
}

Status ToggleOptionElement(
    Session* session,
    WebView* web_view,
    const std::string& element_id) {
  bool is_selected;
  Status status = IsOptionElementSelected(
      session, web_view, element_id, &is_selected);
  if (status.IsError())
    return status;
  return SetOptionElementSelected(session, web_view, element_id, !is_selected);
}

Status ScrollElementIntoView(
    Session* session,
    WebView* web_view,
    const std::string& id,
    const WebPoint* offset,
    WebPoint* location) {
  WebRect region;
  Status status = GetElementRegion(session, web_view, id, &region);
  if (status.IsError())
    return status;
  status = ScrollElementRegionIntoView(session, web_view, id, region,
      false /* center */, std::string(), location);
  if (status.IsError())
    return status;
  if (offset)
    location->Offset(offset->x, offset->y);
  else
    location->Offset(region.size.width / 2, region.size.height / 2);
  return Status(kOk);
}

Status ScrollElementRegionIntoView(
    Session* session,
    WebView* web_view,
    const std::string& element_id,
    const WebRect& region,
    bool center,
    const std::string& clickable_element_id,
    WebPoint* location) {
  WebPoint region_offset = region.origin;
  WebSize region_size = region.size;
  Status status = ScrollElementRegionIntoViewHelper(
      session->GetCurrentFrameId(), web_view, element_id, region,
      center, clickable_element_id, &region_offset);
  if (status.IsError())
    return status;
  const char kFindSubFrameScript[] =
      "function(xpath) {"
      "  return document.evaluate(xpath, document, null,"
      "      XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
      "}";
  for (std::list<FrameInfo>::reverse_iterator rit = session->frames.rbegin();
       rit != session->frames.rend(); ++rit) {
    base::ListValue args;
    args.AppendString(
        base::StringPrintf("//*[@cd_frame_id_ = '%s']",
                           rit->chromedriver_frame_id.c_str()));
    std::unique_ptr<base::Value> result;
    status = web_view->CallFunction(
        rit->parent_frame_id, kFindSubFrameScript, args, &result);
    if (status.IsError())
      return status;
    const base::DictionaryValue* element_dict;
    if (!result->GetAsDictionary(&element_dict))
      return Status(kUnknownError, "no element reference returned by script");
    std::string frame_element_id;
    if (!element_dict->GetString(kElementKey, &frame_element_id))
      return Status(kUnknownError, "failed to locate a sub frame");

    // Modify |region_offset| by the frame's border.
    int border_left = -1;
    int border_top = -1;
    status = GetElementBorder(
        rit->parent_frame_id, web_view, frame_element_id,
        &border_left, &border_top);
    if (status.IsError())
      return status;
    region_offset.Offset(border_left, border_top);

    status = ScrollElementRegionIntoViewHelper(
        rit->parent_frame_id, web_view, frame_element_id,
        WebRect(region_offset, region_size),
        center, frame_element_id, &region_offset);
    if (status.IsError())
      return status;
  }
  *location = region_offset;
  return Status(kOk);
}
