// Copyright 2019 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 "third_party/blink/renderer/core/content_capture/task_session.h"

#include <utility>

#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"

namespace blink {

namespace {
bool IsConstantStreamingEnabled() {
  return base::FeatureList::IsEnabled(
      features::kContentCaptureConstantStreaming);
}

}  // namespace

TaskSession::DocumentSession::DocumentSession(const Document& document,
                                              SentNodeCountCallback& callback)
    : document_(&document), callback_(callback) {}

TaskSession::DocumentSession::~DocumentSession() {
  if (callback_.has_value())
    callback_.value().Run(total_sent_nodes_);
}

bool TaskSession::DocumentSession::AddDetachedNode(const Node& node) {
  // Take the node out of |sent_nodes|, otherwise, the |node| would be found
  // invisible in next capturing and be reported as the removed node again.
  if (sent_nodes_.Take(&node)) {
    detached_nodes_.emplace_back(reinterpret_cast<int64_t>(&node));
    return true;
  }
  return false;
}

WebVector<int64_t> TaskSession::DocumentSession::MoveDetachedNodes() {
  return std::move(detached_nodes_);
}

ContentHolder* TaskSession::DocumentSession::GetNextUnsentNode() {
  while (!captured_content_.IsEmpty()) {
    auto node = captured_content_.begin()->key;
    const gfx::Rect rect = captured_content_.Take(node);
    if (node && node->GetLayoutObject() && !sent_nodes_.Contains(node)) {
      sent_nodes_.insert(WeakMember<const Node>(node));
      total_sent_nodes_++;
      return MakeGarbageCollected<ContentHolder>(node, rect);
    }
  }
  return nullptr;
}

ContentHolder* TaskSession::DocumentSession::GetNextChangedNode() {
  while (!changed_content_.IsEmpty()) {
    auto node = changed_content_.begin()->key;
    const gfx::Rect rect = changed_content_.Take(node);
    if (node.Get() && node->GetLayoutObject()) {
      total_sent_nodes_++;
      return MakeGarbageCollected<ContentHolder>(node, rect);
    }
  }
  return nullptr;
}

bool TaskSession::DocumentSession::AddChangedNode(Node& node) {
  // No need to save the node that hasn't been sent because it will be captured
  // once being on screen.
  if (sent_nodes_.Contains(&node)) {
    changed_nodes_.insert(WeakMember<Node>(&node));
    return true;
  }
  return false;
}

void TaskSession::DocumentSession::OnContentCaptured(
    Node& node,
    const gfx::Rect& visual_rect) {
  if (changed_nodes_.Take(&node)) {
    changed_content_.Set(WeakMember<Node>(&node), visual_rect);
  } else {
    if (IsConstantStreamingEnabled()) {
      if (auto value = sent_nodes_.Take(&node))
        visible_sent_nodes_.insert(value);
      else
        captured_content_.Set(WeakMember<Node>(&node), visual_rect);
    } else {
      if (!sent_nodes_.Contains(&node))
        captured_content_.Set(WeakMember<Node>(&node), visual_rect);
      // else |node| has been sent and unchanged.
    }
  }
}

void TaskSession::DocumentSession::OnGroupingComplete() {
  if (!IsConstantStreamingEnabled())
    return;

  // All nodes in |sent_nodes_| aren't visible any more, remove them.
  for (auto weak_node : sent_nodes_) {
    if (auto* node = weak_node.Get())
      detached_nodes_.emplace_back(reinterpret_cast<int64_t>(node));
  }
  // |visible_sent_nodes_| are still visible and moved to |sent_nodes_|.
  sent_nodes_.swap(visible_sent_nodes_);
  visible_sent_nodes_.clear();
  // Any node in |changed_nodes_| isn't visible any more and shall be clear.
  changed_nodes_.clear();
}

void TaskSession::DocumentSession::Trace(Visitor* visitor) const {
  visitor->Trace(captured_content_);
  visitor->Trace(changed_content_);
  visitor->Trace(document_);
  visitor->Trace(sent_nodes_);
  visitor->Trace(visible_sent_nodes_);
  visitor->Trace(changed_nodes_);
}

void TaskSession::DocumentSession::Reset() {
  changed_content_.clear();
  captured_content_.clear();
  detached_nodes_.Clear();
  sent_nodes_.clear();
  visible_sent_nodes_.clear();
  changed_nodes_.clear();
}

TaskSession::TaskSession() = default;

TaskSession::DocumentSession* TaskSession::GetNextUnsentDocumentSession() {
  for (auto& doc : to_document_session_.Values()) {
    if (!doc->HasUnsentData())
      continue;
    return doc;
  }
  has_unsent_data_ = false;
  return nullptr;
}

void TaskSession::SetCapturedContent(
    const Vector<cc::NodeInfo>& captured_content) {
  DCHECK(!HasUnsentData());
  DCHECK(!captured_content.IsEmpty());
  GroupCapturedContentByDocument(captured_content);
  has_unsent_data_ = true;
}

void TaskSession::GroupCapturedContentByDocument(
    const Vector<cc::NodeInfo>& captured_content) {
  // In rare cases, the same node could have multiple entries in the
  // |captured_content|, but the visual_rect are almost same, we just let the
  // later replace the previous.
  for (const auto& i : captured_content) {
    if (Node* node = DOMNodeIds::NodeForId(i.node_id)) {
      EnsureDocumentSession(node->GetDocument())
          .OnContentCaptured(*node, i.visual_rect);
    }
  }
  for (auto doc_session : to_document_session_.Values()) {
    doc_session->OnGroupingComplete();
  }
}

void TaskSession::OnNodeDetached(const Node& node) {
  if (EnsureDocumentSession(node.GetDocument()).AddDetachedNode(node))
    has_unsent_data_ = true;
}

void TaskSession::OnNodeChanged(Node& node) {
  if (EnsureDocumentSession(node.GetDocument()).AddChangedNode(node))
    has_unsent_data_ = true;
}

TaskSession::DocumentSession& TaskSession::EnsureDocumentSession(
    const Document& doc) {
  DocumentSession* doc_session = GetDocumentSession(doc);
  if (!doc_session) {
    doc_session = MakeGarbageCollected<DocumentSession>(doc, callback_);
    to_document_session_.insert(&doc, doc_session);
  }
  return *doc_session;
}

TaskSession::DocumentSession* TaskSession::GetDocumentSession(
    const Document& document) const {
  auto it = to_document_session_.find(&document);
  if (it == to_document_session_.end())
    return nullptr;
  return it->value;
}

void TaskSession::Trace(Visitor* visitor) const {
  visitor->Trace(to_document_session_);
}

void TaskSession::ClearDocumentSessionsForTesting() {
  to_document_session_.clear();
}

}  // namespace blink
