// Copyright 2013 The Flutter 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 "impeller/core/capture.h"

#include <initializer_list>
#include <memory>

namespace impeller {

//-----------------------------------------------------------------------------
/// CaptureProperty
///

CaptureProperty::CaptureProperty(const std::string& label, Options options)
    : CaptureCursorListElement(label), options(options) {}

CaptureProperty::~CaptureProperty() = default;

bool CaptureProperty::MatchesCloselyEnough(const CaptureProperty& other) const {
  if (label != other.label) {
    return false;
  }
  if (GetType() != other.GetType()) {
    return false;
  }
  return true;
}

#define _CAPTURE_PROPERTY_CAST_DEFINITION(type_name, pascal_name, lower_name) \
  std::optional<type_name> CaptureProperty::As##pascal_name() const {         \
    if (GetType() != Type::k##pascal_name) {                                  \
      return std::nullopt;                                                    \
    }                                                                         \
    return reinterpret_cast<const Capture##pascal_name##Property*>(this)      \
        ->value;                                                              \
  }

_FOR_EACH_CAPTURE_PROPERTY(_CAPTURE_PROPERTY_CAST_DEFINITION);

#define _CAPTURE_PROPERTY_DEFINITION(type_name, pascal_name, lower_name)       \
  Capture##pascal_name##Property::Capture##pascal_name##Property(              \
      const std::string& label, type_name value, Options options)              \
      : CaptureProperty(label, options), value(std::move(value)) {}            \
                                                                               \
  std::shared_ptr<Capture##pascal_name##Property>                              \
      Capture##pascal_name##Property::Make(const std::string& label,           \
                                           type_name value, Options options) { \
    auto result = std::shared_ptr<Capture##pascal_name##Property>(             \
        new Capture##pascal_name##Property(label, std::move(value), options)); \
    return result;                                                             \
  }                                                                            \
                                                                               \
  CaptureProperty::Type Capture##pascal_name##Property::GetType() const {      \
    return Type::k##pascal_name;                                               \
  }                                                                            \
                                                                               \
  void Capture##pascal_name##Property::Invoke(                                 \
      const CaptureProcTable& proc_table) {                                    \
    proc_table.lower_name(*this);                                              \
  }

_FOR_EACH_CAPTURE_PROPERTY(_CAPTURE_PROPERTY_DEFINITION);

//-----------------------------------------------------------------------------
/// CaptureElement
///

CaptureElement::CaptureElement(const std::string& label)
    : CaptureCursorListElement(label) {}

std::shared_ptr<CaptureElement> CaptureElement::Make(const std::string& label) {
  return std::shared_ptr<CaptureElement>(new CaptureElement(label));
}

void CaptureElement::Rewind() {
  properties.Rewind();
  children.Rewind();
}

bool CaptureElement::MatchesCloselyEnough(const CaptureElement& other) const {
  return label == other.label;
}

//-----------------------------------------------------------------------------
/// Capture
///

Capture::Capture() = default;

#ifdef IMPELLER_ENABLE_CAPTURE
Capture::Capture(const std::string& label)
    : element_(CaptureElement::Make(label)), active_(true) {
  element_->label = label;
}
#else
Capture::Capture(const std::string& label) {}
#endif

Capture Capture::MakeInactive() {
  return Capture();
}

std::shared_ptr<CaptureElement> Capture::GetElement() const {
#ifdef IMPELLER_ENABLE_CAPTURE
  return element_;
#else
  return nullptr;
#endif
}

void Capture::Rewind() {
  return GetElement()->Rewind();
}

#ifdef IMPELLER_ENABLE_CAPTURE
#define _CAPTURE_PROPERTY_RECORDER_DEFINITION(type_name, pascal_name,          \
                                              lower_name)                      \
  type_name Capture::Add##pascal_name(std::string_view label, type_name value, \
                                      CaptureProperty::Options options) {      \
    if (!active_) {                                                            \
      return value;                                                            \
    }                                                                          \
    FML_DCHECK(element_ != nullptr);                                           \
                                                                               \
    std::string label_clone = std::string(label);                              \
    auto new_value = Capture##pascal_name##Property::Make(                     \
        label_clone, std::move(value), options);                               \
                                                                               \
    auto next = std::reinterpret_pointer_cast<Capture##pascal_name##Property>( \
        element_->properties.GetNext(std::move(new_value), options.readonly)); \
                                                                               \
    return next->value;                                                        \
  }

_FOR_EACH_CAPTURE_PROPERTY(_CAPTURE_PROPERTY_RECORDER_DEFINITION);
#endif

//-----------------------------------------------------------------------------
/// CaptureContext
///

#ifdef IMPELLER_ENABLE_CAPTURE
CaptureContext::CaptureContext() : active_(true) {}
CaptureContext::CaptureContext(std::initializer_list<std::string> allowlist)
    : active_(true), allowlist_(allowlist) {}
#else
CaptureContext::CaptureContext() {}
CaptureContext::CaptureContext(std::initializer_list<std::string> allowlist) {}
#endif

CaptureContext::CaptureContext(CaptureContext::InactiveFlag) {}

CaptureContext CaptureContext::MakeInactive() {
  return CaptureContext(InactiveFlag{});
}

CaptureContext CaptureContext::MakeAllowlist(
    std::initializer_list<std::string> allowlist) {
  return CaptureContext(allowlist);
}

bool CaptureContext::IsActive() const {
#ifdef IMPELLER_ENABLE_CAPTURE
  return active_;
#else
  return false;
#endif
}

void CaptureContext::Rewind() {
#ifdef IMPELLER_ENABLE_CAPTURE
  for (auto& [name, capture] : documents_) {
    capture.GetElement()->Rewind();
  }
#else
  return;
#endif
}

Capture CaptureContext::GetDocument(const std::string& label) {
#ifdef IMPELLER_ENABLE_CAPTURE
  if (!active_) {
    return Capture::MakeInactive();
  }

  if (allowlist_.has_value()) {
    if (allowlist_->find(label) == allowlist_->end()) {
      return Capture::MakeInactive();
    }
  }

  auto found = documents_.find(label);
  if (found != documents_.end()) {
    // Always rewind when fetching an existing document.
    found->second.Rewind();
    return found->second;
  }

  auto new_document = Capture(label);
  documents_.emplace(label, new_document);
  return new_document;
#else
  return Capture::MakeInactive();
#endif
}

bool CaptureContext::DoesDocumentExist(const std::string& label) const {
#ifdef IMPELLER_ENABLE_CAPTURE
  if (!active_) {
    return false;
  }
  return documents_.find(label) != documents_.end();
#else
  return false;
#endif
}

}  // namespace impeller
