// Copyright 2019 The Fuchsia 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fit/single_threaded_executor.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/inspect/service/cpp/service.h>
#include <lib/stdcompat/variant.h>
#include <lib/sys/cpp/component_context.h>

#include <string>
#include <vector>

#include <test/inspect/validate/cpp/fidl.h>

#include "fuchsia/inspect/cpp/fidl.h"
#include "lib/inspect/service/cpp/service.h"
#include "lib/vfs/cpp/pseudo_dir.h"
#include "lib/vfs/cpp/service.h"

using cpp17::get;
using cpp17::holds_alternative;
using inspect::LazyNode;
using test::inspect::validate::Action;
using test::inspect::validate::InitializationParams;
using test::inspect::validate::LazyAction;
using test::inspect::validate::LinkDisposition;
using test::inspect::validate::NumberType;
using test::inspect::validate::ROOT_ID;
using test::inspect::validate::TestResult;

using Value =
    cpp17::variant<cpp17::monostate, inspect::Node, inspect::IntProperty, inspect::UintProperty,
                   inspect::DoubleProperty, inspect::StringProperty, inspect::ByteVectorProperty,
                   inspect::BoolProperty, inspect::IntArray, inspect::UintArray,
                   inspect::DoubleArray, inspect::LinearIntHistogram, inspect::LinearUintHistogram,
                   inspect::LinearDoubleHistogram, inspect::ExponentialIntHistogram,
                   inspect::ExponentialUintHistogram, inspect::ExponentialDoubleHistogram>;

class Actor {
 public:
  Actor() : inspector_() {}

  Actor(inspect::InspectSettings settings) : inspector_(settings) {}

  inspect::Inspector& inspector() { return inspector_; }

  TestResult Act(const Action& action) {
    switch (action.Which()) {
      case Action::Tag::kCreateNode:
        return HandleCreateNode(action);
      case Action::Tag::kDeleteNode:
        return HandleDeleteNode(action);
      case Action::Tag::kDeleteProperty:
        return HandleDeleteProperty(action);
      case Action::Tag::kCreateNumericProperty:
        return HandleCreateNumeric(action);
      case Action::Tag::kCreateBytesProperty:
        return HandleCreateBytes(action);
      case Action::Tag::kCreateStringProperty:
        return HandleCreateString(action);
      case Action::Tag::kCreateBoolProperty:
        return HandleCreateBool(action);
      case Action::Tag::kSetNumber:
        return HandleSetNumber(action);
      case Action::Tag::kAddNumber:
        return HandleAddNumber(action);
      case Action::Tag::kSubtractNumber:
        return HandleSubtractNumber(action);
      case Action::Tag::kSetString:
        return HandleSetString(action);
      case Action::Tag::kSetBytes:
        return HandleSetBytes(action);
      case Action::Tag::kSetBool:
        return HandleSetBool(action);
      case Action::Tag::kCreateArrayProperty:
        return HandleCreateArray(action);
      case Action::Tag::kArraySet:
        return HandleArraySet(action);
      case Action::Tag::kArrayAdd:
        return HandleArrayAdd(action);
      case Action::Tag::kArraySubtract:
        return HandleArraySubtract(action);
      case Action::Tag::kCreateLinearHistogram:
        return HandleCreateLinearHistogram(action);
      case Action::Tag::kCreateExponentialHistogram:
        return HandleCreateExponentialHistogram(action);
      case Action::Tag::kInsert:
        return HandleInsert(action);
      case Action::Tag::kInsertMultiple:
        return HandleInsertMultiple(action);
      default:
        return TestResult::UNIMPLEMENTED;
    }
  }

  TestResult ActLazy(const LazyAction& lazy_action) {
    switch (lazy_action.Which()) {
      case LazyAction::Tag::kCreateLazyNode:
        return HandleCreateLazyNode(lazy_action);
      case LazyAction::Tag::kDeleteLazyNode:
        return HandleDeleteLazyNode(lazy_action);
      default:
        return TestResult::UNIMPLEMENTED;
    }
  }

 private:
  template <typename T>
  T* GetFromValueMap(uint64_t id) {
    auto it = value_map_.find(id);
    if (it == value_map_.end()) {
      return nullptr;
    }

    if (!holds_alternative<T>(it->second)) {
      return nullptr;
    }

    return &get<T>(it->second);
  }

  inspect::Node* GetNode(uint64_t id) {
    if (id == ROOT_ID) {
      return &inspector_.GetRoot();
    } else {
      return GetFromValueMap<inspect::Node>(id);
    }
  }

  bool ValueMapContains(uint64_t id) { return value_map_.find(id) != value_map_.end(); }

  bool LazyChildrenMapContains(uint64_t id) {
    return lazy_children_map_.find(id) != lazy_children_map_.end();
  }

  // Emplace all currently held Values into the underlying Inspector object.
  // We do this so that when this instance goes of scope, the Value objects don't call their
  // destructors.
  void Freeze() {
    for (auto& [k, v] : value_map_) {
      inspector_.emplace(std::move(v));
    }
    value_map_.clear();
  }

  TestResult HandleCreateNode(const Action& raw_action) {
    auto& action = raw_action.create_node();

    if (ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    value_map_.emplace(action.id, parent->CreateChild(action.name));

    return TestResult::OK;
  }

  TestResult HandleDeleteNode(const Action& raw_action) {
    auto& action = raw_action.delete_node();

    if (!ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    value_map_.erase(action.id);

    return TestResult::OK;
  }

  TestResult HandleCreateNumeric(const Action& raw_action) {
    auto& action = raw_action.create_numeric_property();

    if (ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    if (action.value.is_int_t()) {
      value_map_.emplace(action.id, parent->CreateInt(action.name, action.value.int_t()));
    } else if (action.value.is_uint_t()) {
      value_map_.emplace(action.id, parent->CreateUint(action.name, action.value.uint_t()));
    } else if (action.value.is_double_t()) {
      value_map_.emplace(action.id, parent->CreateDouble(action.name, action.value.double_t()));
    } else {
      return TestResult::UNIMPLEMENTED;
    }

    return TestResult::OK;
  }

  TestResult HandleCreateBytes(const Action& raw_action) {
    auto& action = raw_action.create_bytes_property();

    if (ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    value_map_.emplace(action.id, parent->CreateByteVector(action.name, action.value));

    return TestResult::OK;
  }

  TestResult HandleCreateString(const Action& raw_action) {
    auto& action = raw_action.create_string_property();

    if (ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    value_map_.emplace(action.id, parent->CreateString(action.name, action.value));

    return TestResult::OK;
  }

  TestResult HandleCreateBool(const Action& raw_action) {
    auto& action = raw_action.create_bool_property();

    if (ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    value_map_.emplace(action.id, parent->CreateBool(action.name, action.value));

    return TestResult::OK;
  }

  TestResult HandleDeleteProperty(const Action& raw_action) {
    auto& action = raw_action.delete_property();

    if (!ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    value_map_.erase(action.id);

    return TestResult::OK;
  }

  // Helpful macro for deduplicating the 3 operations for numbers (Set, Add, and Subtract).
#define CREATE_NUMERIC_HANDLER(OP_NAME, TYPE_FUNC)                           \
  TestResult Handle##OP_NAME##Number(const Action& raw_action) {             \
    auto& action = raw_action.TYPE_FUNC();                                   \
                                                                             \
    if (action.value.is_int_t()) {                                           \
      if (auto* val = GetFromValueMap<inspect::IntProperty>(action.id)) {    \
        val->OP_NAME(action.value.int_t());                                  \
        return TestResult::OK;                                               \
      }                                                                      \
    } else if (action.value.is_uint_t()) {                                   \
      if (auto* val = GetFromValueMap<inspect::UintProperty>(action.id)) {   \
        val->OP_NAME(action.value.uint_t());                                 \
        return TestResult::OK;                                               \
      }                                                                      \
    } else if (action.value.is_double_t()) {                                 \
      if (auto* val = GetFromValueMap<inspect::DoubleProperty>(action.id)) { \
        val->OP_NAME(action.value.double_t());                               \
        return TestResult::OK;                                               \
      }                                                                      \
    } else {                                                                 \
      return TestResult::UNIMPLEMENTED;                                      \
    }                                                                        \
                                                                             \
    return TestResult::FAILED;                                               \
  }

  CREATE_NUMERIC_HANDLER(Add, add_number)
  CREATE_NUMERIC_HANDLER(Subtract, subtract_number)
  CREATE_NUMERIC_HANDLER(Set, set_number)

  TestResult HandleSetString(const Action& raw_action) {
    auto& action = raw_action.set_string();

    if (auto* val = GetFromValueMap<inspect::StringProperty>(action.id)) {
      val->Set(action.value);
      return TestResult::OK;
    } else {
      return TestResult::FAILED;
    }
  }

  TestResult HandleSetBytes(const Action& raw_action) {
    auto& action = raw_action.set_bytes();

    if (auto* val = GetFromValueMap<inspect::ByteVectorProperty>(action.id)) {
      val->Set(action.value);
      return TestResult::OK;
    } else {
      return TestResult::FAILED;
    }
  }

  TestResult HandleSetBool(const Action& raw_action) {
    auto& action = raw_action.set_bool();

    if (auto* val = GetFromValueMap<inspect::BoolProperty>(action.id)) {
      val->Set(action.value);
      return TestResult::OK;
    } else {
      return TestResult::FAILED;
    }
  }

  TestResult HandleCreateArray(const Action& raw_action) {
    auto& action = raw_action.create_array_property();

    if (ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    switch (action.number_type) {
      case NumberType::INT:
        value_map_.emplace(action.id, parent->CreateIntArray(action.name, action.slots));
        break;
      case NumberType::UINT:
        value_map_.emplace(action.id, parent->CreateUintArray(action.name, action.slots));
        break;
      case NumberType::DOUBLE:
        value_map_.emplace(action.id, parent->CreateDoubleArray(action.name, action.slots));
        break;
      default:
        return TestResult::UNIMPLEMENTED;
    };

    return TestResult::OK;
  }

  // Helpful macro for deduplicating the 3 operations for arrays (Set, Add, and Subtract).
#define CREATE_ARRAY_HANDLER(OP_NAME, TYPE_FUNC)                          \
  TestResult HandleArray##OP_NAME(const Action& raw_action) {             \
    auto& action = raw_action.TYPE_FUNC();                                \
                                                                          \
    if (action.value.is_int_t()) {                                        \
      if (auto* val = GetFromValueMap<inspect::IntArray>(action.id)) {    \
        val->OP_NAME(action.index, action.value.int_t());                 \
        return TestResult::OK;                                            \
      }                                                                   \
    } else if (action.value.is_uint_t()) {                                \
      if (auto* val = GetFromValueMap<inspect::UintArray>(action.id)) {   \
        val->OP_NAME(action.index, action.value.uint_t());                \
        return TestResult::OK;                                            \
      }                                                                   \
    } else if (action.value.is_double_t()) {                              \
      if (auto* val = GetFromValueMap<inspect::DoubleArray>(action.id)) { \
        val->OP_NAME(action.index, action.value.double_t());              \
        return TestResult::OK;                                            \
      }                                                                   \
    } else {                                                              \
      return TestResult::UNIMPLEMENTED;                                   \
    }                                                                     \
                                                                          \
    return TestResult::FAILED;                                            \
  }

  CREATE_ARRAY_HANDLER(Set, array_set)
  CREATE_ARRAY_HANDLER(Add, array_add)
  CREATE_ARRAY_HANDLER(Subtract, array_subtract)

  TestResult HandleCreateLinearHistogram(const Action& raw_action) {
    auto& action = raw_action.create_linear_histogram();

    if (ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    if (action.floor.is_int_t()) {
      value_map_.emplace(
          action.id, parent->CreateLinearIntHistogram(action.name, action.floor.int_t(),
                                                      action.step_size.int_t(), action.buckets));
    } else if (action.floor.is_uint_t()) {
      value_map_.emplace(
          action.id, parent->CreateLinearUintHistogram(action.name, action.floor.uint_t(),
                                                       action.step_size.uint_t(), action.buckets));
    } else if (action.floor.is_double_t()) {
      value_map_.emplace(action.id, parent->CreateLinearDoubleHistogram(
                                        action.name, action.floor.double_t(),
                                        action.step_size.double_t(), action.buckets));
    } else {
      return TestResult::UNIMPLEMENTED;
    }

    return TestResult::OK;
  }

  TestResult HandleCreateExponentialHistogram(const Action& raw_action) {
    auto& action = raw_action.create_exponential_histogram();

    if (ValueMapContains(action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    if (action.floor.is_int_t()) {
      value_map_.emplace(action.id,
                         parent->CreateExponentialIntHistogram(
                             action.name, action.floor.int_t(), action.initial_step.int_t(),
                             action.step_multiplier.int_t(), action.buckets));
    } else if (action.floor.is_uint_t()) {
      value_map_.emplace(action.id,
                         parent->CreateExponentialUintHistogram(
                             action.name, action.floor.uint_t(), action.initial_step.uint_t(),
                             action.step_multiplier.uint_t(), action.buckets));
    } else if (action.floor.is_double_t()) {
      value_map_.emplace(action.id,
                         parent->CreateExponentialDoubleHistogram(
                             action.name, action.floor.double_t(), action.initial_step.double_t(),
                             action.step_multiplier.double_t(), action.buckets));
    } else {
      return TestResult::UNIMPLEMENTED;
    }

    return TestResult::OK;
  }

  TestResult HandleInsert(const Action& raw_action) {
    auto& action = raw_action.insert();

    if (action.value.is_int_t()) {
      if (auto* val = GetFromValueMap<inspect::LinearIntHistogram>(action.id)) {
        val->Insert(action.value.int_t());
      } else if (auto* val = GetFromValueMap<inspect::ExponentialIntHistogram>(action.id)) {
        val->Insert(action.value.int_t());
      } else {
        return TestResult::FAILED;
      }
    } else if (action.value.is_uint_t()) {
      if (auto* val = GetFromValueMap<inspect::LinearUintHistogram>(action.id)) {
        val->Insert(action.value.uint_t());
      } else if (auto* val = GetFromValueMap<inspect::ExponentialUintHistogram>(action.id)) {
        val->Insert(action.value.uint_t());
      } else {
        return TestResult::FAILED;
      }
    } else if (action.value.is_double_t()) {
      if (auto* val = GetFromValueMap<inspect::LinearDoubleHistogram>(action.id)) {
        val->Insert(action.value.double_t());
      } else if (auto* val = GetFromValueMap<inspect::ExponentialDoubleHistogram>(action.id)) {
        val->Insert(action.value.double_t());
      } else {
        return TestResult::FAILED;
      }
    } else {
      return TestResult::UNIMPLEMENTED;
    }

    return TestResult::OK;
  }

  TestResult HandleInsertMultiple(const Action& raw_action) {
    auto& action = raw_action.insert_multiple();

    if (action.value.is_int_t()) {
      if (auto* val = GetFromValueMap<inspect::LinearIntHistogram>(action.id)) {
        val->Insert(action.value.int_t(), action.count);
      } else if (auto* val = GetFromValueMap<inspect::ExponentialIntHistogram>(action.id)) {
        val->Insert(action.value.int_t(), action.count);
      } else {
        return TestResult::FAILED;
      }
    } else if (action.value.is_uint_t()) {
      if (auto* val = GetFromValueMap<inspect::LinearUintHistogram>(action.id)) {
        val->Insert(action.value.uint_t(), action.count);
      } else if (auto* val = GetFromValueMap<inspect::ExponentialUintHistogram>(action.id)) {
        val->Insert(action.value.uint_t(), action.count);
      } else {
        return TestResult::FAILED;
      }
    } else if (action.value.is_double_t()) {
      if (auto* val = GetFromValueMap<inspect::LinearDoubleHistogram>(action.id)) {
        val->Insert(action.value.double_t(), action.count);
      } else if (auto* val = GetFromValueMap<inspect::ExponentialDoubleHistogram>(action.id)) {
        val->Insert(action.value.double_t(), action.count);
      } else {
        return TestResult::FAILED;
      }
    } else {
      return TestResult::UNIMPLEMENTED;
    }

    return TestResult::OK;
  }

  TestResult HandleCreateLazyNode(const LazyAction& raw_lazy_action) {
    auto& lazy_action = raw_lazy_action.create_lazy_node();

    if (LazyChildrenMapContains(lazy_action.id)) {
      return TestResult::FAILED;
    }

    auto* parent = GetNode(lazy_action.parent);
    if (!parent) {
      return TestResult::FAILED;
    }

    Actor actor;
    for (const auto& action : lazy_action.actions) {
      actor.Act(action);
    }
    actor.Freeze();
    auto cb = [clone = std::move(actor.inspector())]() { return fit::make_ok_promise(clone); };

    if (lazy_action.disposition == LinkDisposition::CHILD) {
      lazy_children_map_.emplace(lazy_action.id, parent->CreateLazyNode(lazy_action.name, cb));
    } else {
      lazy_children_map_.emplace(lazy_action.id, parent->CreateLazyValues(lazy_action.name, cb));
    }

    return TestResult::OK;
  }

  TestResult HandleDeleteLazyNode(const LazyAction& raw_lazy_action) {
    auto& lazy_action = raw_lazy_action.delete_lazy_node();

    if (!LazyChildrenMapContains(lazy_action.id)) {
      return TestResult::FAILED;
    }

    lazy_children_map_.erase(lazy_action.id);

    return TestResult::OK;
  }

  inspect::Inspector inspector_;
  std::map<uint64_t, Value> value_map_;
  std::map<uint64_t, LazyNode> lazy_children_map_;
};

class Puppet : public test::inspect::validate::Validate {
 public:
  explicit Puppet(std::unique_ptr<sys::ComponentContext> context) : context_(std::move(context)) {
    context_->outgoing()->AddPublicService(bindings_.GetHandler(this));
    diagnostics_directory_ = context_->outgoing()->GetOrCreateDirectory("diagnostics");
  }

  void Initialize(InitializationParams params, InitializeCallback callback) override {
    if (actor_ != nullptr) {
      callback(zx::vmo(ZX_HANDLE_INVALID), TestResult::ILLEGAL);
      return;
    }
    actor_ = std::make_unique<Actor>(inspect::InspectSettings{.maximum_size = params.vmoSize()});

    if (!bool(actor_->inspector())) {
      callback(zx::vmo(ZX_HANDLE_INVALID), TestResult::FAILED);
    } else {
      callback(actor_->inspector().DuplicateVmo(), TestResult::OK);
    }
  }

  void InitializeTree(InitializationParams params, InitializeTreeCallback callback) override {
    if (actor_ != nullptr) {
      callback(nullptr, TestResult::ILLEGAL);
      return;
    }
    actor_ = std::make_unique<Actor>(inspect::InspectSettings{.maximum_size = params.vmoSize()});

    tree_handler_ = inspect::MakeTreeHandler(&actor_->inspector());
    fuchsia::inspect::TreePtr tree_ptr;
    tree_handler_(tree_ptr.NewRequest());
    callback(std::move(tree_ptr), TestResult::OK);
  }

  void Publish(PublishCallback callback) override {
    if (actor_ == nullptr) {
      callback(TestResult::ILLEGAL);
      return;
    }

    diagnostics_directory_->AddEntry(
        fuchsia::inspect::Tree::Name_,
        std::make_unique<vfs::Service>(inspect::MakeTreeHandler(&actor_->inspector())));
    callback(TestResult::OK);
  }

  void Unpublish(PublishCallback callback) override {
    diagnostics_directory_->RemoveEntry(fuchsia::inspect::Tree::Name_);
    callback(TestResult::OK);
  }

  void Act(Action action, ActCallback callback) override {
    if (actor_ == nullptr) {
      callback(TestResult::ILLEGAL);
    } else {
      callback(actor_->Act(action));
    }
  }

  void ActLazy(LazyAction lazy_action, ActLazyCallback callback) override {
    if (actor_ == nullptr) {
      callback(TestResult::ILLEGAL);
    } else {
      callback(actor_->ActLazy(lazy_action));
    }
  }

 private:
  std::unique_ptr<sys::ComponentContext> context_;
  vfs::PseudoDir* diagnostics_directory_;
  fidl::BindingSet<test::inspect::validate::Validate> bindings_;
  fidl::InterfaceRequestHandler<fuchsia::inspect::Tree> tree_handler_;
  std::unique_ptr<Actor> actor_;
};

int main(int argc, const char** argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  Puppet puppet(sys::ComponentContext::CreateAndServeOutgoingDirectory());

  loop.Run();
  return 0;
}
