// Copyright 2017 The Chromium Embedded Framework Authors. Portions copyright
// 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.

// Base class implementation for CEF Acccessibility node. This is subclassed and
// used by both IAccessible/NSAccessibility protocol implementation.

#include "tests/cefclient/browser/osr_accessibility_node.h"

#include "tests/cefclient/browser/osr_accessibility_helper.h"

namespace client {

OsrAXNode::OsrAXNode(const CefString& treeId,
                     int nodeId,
                     CefRefPtr<CefDictionaryValue> value,
                     OsrAccessibilityHelper* helper)
    : tree_id_(treeId),
      node_id_(nodeId),
      platform_accessibility_(nullptr),
      parent_(nullptr),
      offset_container_id_(-1),
      accessibility_helper_(helper) {
  UpdateValue(value);
}

void OsrAXNode::UpdateLocation(CefRefPtr<CefDictionaryValue> value) {
  // Update Bounds
  if (value->HasKey("bounds")) {
    CefRefPtr<CefDictionaryValue> loc = value->GetDictionary("bounds");
    if (loc) {
      location_ = CefRect(loc->GetDouble("x"), loc->GetDouble("y"),
                          loc->GetDouble("width"), loc->GetDouble("height"));
    }
  }
  // Update offsets
  if (value->HasKey("offset_container_id")) {
    offset_container_id_ = OsrAccessibilityHelper::CastToInt(
        value->GetValue("offset_container_id"));
  }
}

void OsrAXNode::UpdateValue(CefRefPtr<CefDictionaryValue> value) {
  if (value->HasKey("role"))
    role_ = value->GetString("role");

  if (value->HasKey("child_ids")) {
    CefRefPtr<CefListValue> childs = value->GetList("child_ids");
    // Reset child Ids
    child_ids_.clear();
    for (size_t idx = 0; idx < childs->GetSize(); idx++)
      child_ids_.push_back(
          OsrAccessibilityHelper::CastToInt(childs->GetValue(idx)));
  }
  // Update Location
  if (value->HasKey("location")) {
    CefRefPtr<CefDictionaryValue> loc = value->GetDictionary("location");
    if (loc) {
      location_ = CefRect(loc->GetDouble("x"), loc->GetDouble("y"),
                          loc->GetDouble("width"), loc->GetDouble("height"));
    }
  }
  // Update offsets
  if (value->HasKey("offset_container_id")) {
    offset_container_id_ = OsrAccessibilityHelper::CastToInt(
        value->GetValue("offset_container_id"));
  }
  // Update attributes
  if (value->HasKey("attributes")) {
    child_tree_id_ = "";

    attributes_ = value->GetDictionary("attributes");

    if (attributes_) {
      scroll_.x = attributes_->HasKey("scrollX")
                      ? OsrAccessibilityHelper::CastToInt(
                            attributes_->GetValue("scrollX"))
                      : 0;
      scroll_.y = attributes_->HasKey("scrollY")
                      ? OsrAccessibilityHelper::CastToInt(
                            attributes_->GetValue("scrollY"))
                      : 0;
    }

    if (attributes_ && attributes_->HasKey("childTreeId")) {
      child_tree_id_ = attributes_->GetString("childTreeId");
    }
    if (attributes_ && attributes_->HasKey("name"))
      name_ = attributes_->GetString("name");
    if (attributes_ && attributes_->HasKey("value"))
      value_ = attributes_->GetString("value");
    if (attributes_ && attributes_->HasKey("description"))
      description_ = attributes_->GetString("description");
  }
}

CefWindowHandle OsrAXNode::GetWindowHandle() const {
  if (accessibility_helper_)
    return accessibility_helper_->GetWindowHandle();
  return NULL;
}

CefRefPtr<CefBrowser> OsrAXNode::GetBrowser() const {
  if (accessibility_helper_)
    return accessibility_helper_->GetBrowser();
  return nullptr;
}

void OsrAXNode::SetParent(OsrAXNode* parent) {
  parent_ = parent;
}

CefRect OsrAXNode::AxLocation() const {
  CefRect loc = location_;
  loc.x -= scroll_.x;
  loc.y -= scroll_.y;
  OsrAXNode* offsetNode =
      accessibility_helper_->GetNode(OsrAXTreeId(), offset_container_id_);
  if (!offsetNode) {
    OsrAXNode* p = parent_;
    while (p) {
      if (p->OsrAXTreeId() != OsrAXTreeId()) {
        offsetNode = p;
        break;
      }
      p = p->parent_;
    }
  }
  // Add offset from parent Location
  if (offsetNode) {
    CefRect offset = offsetNode->AxLocation();
    loc.x += offset.x;
    loc.y += offset.y;
  }
  return loc;
}

int OsrAXNode::GetChildCount() const {
  int count = static_cast<int>(child_ids_.size());
  if (!child_tree_id_.empty()) {
    OsrAXNode* childTreeRootNode =
        accessibility_helper_->GetTreeRootNode(child_tree_id_);
    if (childTreeRootNode) {
      count++;
    }
  }
  return count;
}

OsrAXNode* OsrAXNode::ChildAtIndex(int index) const {
  int count = static_cast<int>(child_ids_.size());
  if (index < count)
    return accessibility_helper_->GetNode(OsrAXTreeId(), child_ids_[index]);
  if ((index == count) && (!child_tree_id_.empty())) {
    OsrAXNode* childTreeRootNode =
        accessibility_helper_->GetTreeRootNode(child_tree_id_);
    if (childTreeRootNode) {
      return childTreeRootNode;
    }
  }

  return nullptr;
}

// Create and return the platform specific OsrAXNode Object
OsrAXNode* OsrAXNode::CreateNode(const CefString& treeId,
                                 int nodeId,
                                 CefRefPtr<CefDictionaryValue> value,
                                 OsrAccessibilityHelper* helper) {
  return new OsrAXNode(treeId, nodeId, value, helper);
}

}  // namespace client
