// 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/fit/defer.h>
#include <lib/inspect/deprecated/object_dir.h>
#include <lib/inspect/inspect.h>
#include <lib/sys/cpp/component_context.h>

#include <string>

/* Inspection Example App
 *
 * This app demonstrates common features of the Inspect API.
 *
 * The specific application is an employee task manager. Each |Employee| has a
 * number of |Task|s assigned and may have a number of additional |Employee|s
 * reporting to them. The full tree of |Task| and |Employee| are exposed over
 * the Inspect API.
 *
 * We are concerned with obtaining each |Employee|'s individual performance and
 * the performance of their direct reports. In both cases, |EmployeePerformance|
 * is simply the average completion of assigned |Task|s, from 0.0 to 1.0.
 *
 */

namespace {

// Global metric counts.
// Global metrics should be raw pointers that are set back to nullptr when
// deleted. Additional concurrency control should be used in multithreaded
// settings.
inspect::UIntMetric* number_of_employees = nullptr;
inspect::UIntMetric* number_of_tasks = nullptr;

// Set the pointers to global values.
// Returns a deferred_action that automatically sets the global pointers to null
// when it goes out of scope.
fit::deferred_action<fit::closure> SetGlobals(
    inspect::UIntMetric* employee_count, inspect::UIntMetric* task_count) {
  number_of_employees = employee_count;
  number_of_tasks = task_count;
  return fit::defer(fit::closure([] {
    number_of_employees = nullptr;
    number_of_tasks = nullptr;
  }));
}

// Changes the global count of employees by the given amount.
void CountEmployees(int change) {
  if (number_of_employees) {
    number_of_employees->Add(change);
  }
}

// Changes the global count of tasks by the given amount.
void CountTasks(int change) {
  if (number_of_tasks) {
    number_of_tasks->Add(change);
  }
}

}  // namespace

// A |Task| represents something that needs to be done. It consists of a bug
// number for each tracking as well as a human-readable name.
// It also contains a completion ratio out of 1.0 that can be set dynamically.
class Task {
 public:
  // Construct a new |Task|.
  // Note that the constructor takes an |inspect::Node|; this object is
  // provided by the parent to allow linking into the inspect hierarchy.
  Task(std::string bug_number, std::string name, inspect::Node object)
      : bug_number_(std::move(bug_number)),
        name_(std::move(name)),
        object_(std::move(object)) {
    // Increment the global count metric.
    CountTasks(1);

    // Create two |StringProperty| members to hold the data for this |Task|.
    bug_number_property_ = object_.CreateStringProperty("bug", bug_number_);
    name_property_ = object_.CreateStringProperty("name", name_);

    // The completion of the task is an |inspect::DoubleMetric|.
    completion_metric_ = object_.CreateDoubleMetric("completion", 0);
  }

  // Destroy the task by decrementing the global count metric.
  ~Task() { CountTasks(-1); }

  // Sets the completion of the |Task|.
  void SetCompletion(double completion) {
    completion_ = completion < 0 ? 0 : completion > 1 ? 1 : completion;
    completion_metric_.Set(completion_);
  }

  // Gets the completion of the |Task|.
  double GetCompletion() const { return completion_; }

 private:
  std::string bug_number_;
  std::string name_;
  double completion_ = 0;

  // Object for this |Task|. All exposed properties and metrics are rooted on
  // this Object.
  inspect::Node object_;

  // |StringProperty| for bug number and name.
  inspect::StringProperty bug_number_property_;
  inspect::StringProperty name_property_;

  // Metric for this |Task|'s completion.
  inspect::DoubleMetric completion_metric_;
};

// Structure representing an |Employee|'s performance.
// Simply holds the total tasks the |Employee| has and the sum of their
// completion ratios.
struct EmployeePerformance {
  uint64_t total_tasks;
  double total_completion;

  // Calculates average completion.
  double CalculateCompletion() {
    return total_tasks != 0 ? total_completion / total_tasks : 1;
  }

  // Adds another |EmployeePerformance| to this one, useful for getting the
  // average completion of a list of reports.
  EmployeePerformance& operator+=(const EmployeePerformance& other) {
    total_tasks += other.total_tasks;
    total_completion += other.total_completion;
    return *this;
  }
};

// |Employee| represents an individual employee of our company.
// They consist of a name and email, a list of assigned |Task|s, and a list of
// |Employee|s that directly report to this |Employee|.
class Employee {
 public:
  // Create a new |Employee|.
  // Note that the constructor takes an |inspect::Node| that we may use to
  // expose our own metrics, properties, and children Objects.
  Employee(std::string name, std::string email, inspect::Node object)
      : name_(std::move(name)),
        email_(std::move(email)),
        object_(std::move(object)) {
    // Increment the global employee count.
    CountEmployees(1);

    // Create an |inspect::StringProperty| for the name and email of this
    // employee.
    name_property_ = object_.CreateStringProperty("name", name_);
    email_property_ = object_.CreateStringProperty("email", email_);

    // |Task| objects are nested under another child object, called "tasks".
    task_object_ = object_.CreateChild("tasks");

    // Each |Employee| reporting to this |Employee|  are nested under another
    // child object, called "reports".
    report_object_ = object_.CreateChild("reports");

    // Create an |inspect::LazyMetric| for this |Employee|'s personal
    // performance. The "personal_performance" of an |Employee| is the average
    // completion of their |Task|s.
    lazy_metrics_.emplace_back(object_.CreateLazyMetric(
        "personal_performance", [this](component::Metric* out) {
          // Callbacks have an "out" parameter that is set to the desired value.
          // In this case, set it to the double value of our
          // |EmployeePerformance|.
          out->SetDouble(GetPerformance().CalculateCompletion());
        }));

    // Create an |inspect::LazyMetric| for the performance of this
    // |Employee|'s reports. The "report" performance of an |Employee| is the
    // average completion of all |Task|s assigned to their direct reports.
    lazy_metrics_.emplace_back(object_.CreateLazyMetric(
        "report_performance", [this](component::Metric* out) {
          // Add together the performance for each report, and set the result in
          // the out parameter.
          EmployeePerformance perf = {};
          for (const auto& report : reports_) {
            perf += report->GetPerformance();
          }
          out->SetDouble(perf.CalculateCompletion());
        }));
  }

  // Destroy an |Employee| by subtracting from the global employee count.
  ~Employee() { CountEmployees(-1); }

  // |Employee|s may be moved but not copied.
  // This is often necessary because inspect::* types are not copyable.
  Employee(Employee&&) = default;
  Employee(const Employee&) = delete;
  Employee& operator=(Employee&&) = default;
  Employee& operator=(const Employee&) = delete;

  // Add a new |Task| to this |Employee|.
  // |Employee|s always try to assign |Task|s to the report with the least
  // number of existing |Task|s before taking a |Task| a task for themself.
  //
  // Returns a pointer to the |Task| for additional modification.
  Task* AddTask(std::string bug_number, std::string name) {
    size_t least_loaded_count = GetTaskCount();
    Employee* least_loaded_employee = this;

    // Iterate over reports to find the report with the least number of existing
    // tasks.
    for (auto& report : reports_) {
      if (report->GetTaskCount() <= least_loaded_count) {
        least_loaded_count = report->GetTaskCount();
        least_loaded_employee = report.get();
      }
    }

    if (least_loaded_employee == this) {
      // If this |Employee| is the least loaded, take the |Task|...
      return tasks_
          .emplace_back(std::make_unique<Task>(
              std::move(bug_number), std::move(name),
              // Note: We need to pass an Object linked under this Object into
              // the new child. We use |inspect::UniqueName| to assign a
              // globally unique suffix to the child's name.
              task_object_.CreateChild(inspect::UniqueName("task-"))))
          .get();
    } else {
      // ... otherwise, recursively add the |Task| to the least loaded report.
      return least_loaded_employee->AddTask(std::move(bug_number),
                                            std::move(name));
    }
  }

  // Gets the number of |Task|s this |Employee| has.
  size_t GetTaskCount() const { return tasks_.size(); }

  // Add a new |Employee| reporting to this |Employee|.
  Employee* AddReport(std::string name, std::string email) {
    return reports_
        .emplace_back(std::make_unique<Employee>(
            std::move(name), std::string(email),
            // Note: We need to pass an Object linked under this Object into the
            // new child. We use the |email| directly, since elsewhere we
            // guarantee everyone's emails are unique.
            report_object_.CreateChild(std::move(email))))
        .get();
  }

  // Gets the performance for this |Employee|.
  EmployeePerformance GetPerformance() const {
    EmployeePerformance ret = {.total_tasks = tasks_.size(),
                               .total_completion = 0};
    for (const auto& task : tasks_) {
      ret.total_completion += task->GetCompletion();
    }

    return ret;
  }

 private:
  std::string name_;
  std::string email_;

  // Vector of |Task|s assigned to this |Employee|.
  std::vector<std::unique_ptr<Task>> tasks_;
  // Vector of |Employee|s reporting to this |Employee|.
  std::vector<std::unique_ptr<Employee>> reports_;

  // Object under which this |Employee| can expose inspect information.
  inspect::Node object_;

  // Properties for name and email.
  inspect::StringProperty name_property_;
  inspect::StringProperty email_property_;

  // Object under which this |Employee| nests |Task|s.
  inspect::Node task_object_;
  // Object under which this |Employee| nests reporting |Employee|s.
  inspect::Node report_object_;

  // Container for various computed "Lazy" metrics we wish to expose.
  std::vector<inspect::LazyMetric> lazy_metrics_;
};

int main(int argc, const char** argv) {
  // Standard component setup, create an event loop and obtain the
  // |StartupContext|.
  async::Loop loop(&kAsyncLoopConfigAttachToThread);
  auto context = sys::ComponentContext::Create();

  // Create a root object and bind it to out/
  auto root_object_dir = component::ObjectDir::Make("root");
  inspect::Node root_object(root_object_dir);
  fidl::BindingSet<fuchsia::inspect::Inspect> inspect_bindings_;
  context->outgoing()->GetOrCreateDirectory("objects")->AddEntry(
      fuchsia::inspect::Inspect::Name_,
      std::make_unique<vfs::Service>(
          inspect_bindings_.GetHandler(root_object_dir.object().get())));

  // Create global metrics and globally publish pointers to them.
  auto employee_count = root_object.CreateUIntMetric("employee_count", 0);
  auto task_count = root_object.CreateUIntMetric("task_count", 0);
  auto cleanup = SetGlobals(&employee_count, &task_count);

  // Create a CEO |Employee| nested underneath the |root_object|.
  // The name "reporting_tree" will appear as a child of the root object.
  Employee ceo("CEO", "ceo@example.com",
               root_object.CreateChild("reporting_tree"));

  // Create some reports for the CEO, named Bob, Prakash, and Svetlana.
  auto* bob = ceo.AddReport("Bob", "bob@example.com");
  auto* prakash = ceo.AddReport("Prakash", "prakash@example.com");
  auto* svetlana = ceo.AddReport("Svetlana", "svetlana@example.com");

  // Bob has 3 reports: Julie, James, and Jun.
  bob->AddReport("Julie", "julie@example.com");
  bob->AddReport("James", "james@example.com");
  bob->AddReport("Jun", "jun@example.com");

  // Prakash has two reports: Gerald and Nathan.
  prakash->AddReport("Gerald", "gerald@example.com");
  // Nathan is an intern, so assign him a task to complete his training.
  prakash->AddReport("Nathan", "nathan@example.com")
      ->AddTask("ABC-12", "Complete intern code training")
      ->SetCompletion(1);

  // Bob has a lot of corporate tasks to complete, he will give these to people
  // in his reporting tree.
  bob->AddTask("CORP-100", "Promote extra synergy")->SetCompletion(.5);
  bob->AddTask("CORP-101", "Circle back and re-sync")->SetCompletion(.75);
  bob->AddTask("CORP-102", "Look into issue with facilities")
      ->SetCompletion(.8);
  bob->AddTask("CORP-103", "Issue new badges")->SetCompletion(.2);

  // Prakash has a lot of engineering tasks to complete, he will give these to
  // people in his reporting tree.
  prakash->AddTask("ENG-10", "Document key structures")->SetCompletion(1);
  prakash->AddTask("ENG-11", "Write login page")->SetCompletion(.1);
  prakash->AddTask("ENG-12", "Create design for v2")->SetCompletion(.33);

  // Svetlana has a lot of infrastructure tasks to complete, she doesn't
  // currently have reports so she takes these herself.
  svetlana->AddTask("INFRA-100", "Implement new infrastructure")
      ->SetCompletion(1);
  svetlana->AddTask("INFRA-101", "Onboard new users")->SetCompletion(.8);

  // Svetlana hired new people to help with infrastructure.
  svetlana->AddReport("Hector", "hector@example.com");
  svetlana->AddReport("Dianne", "dianne@example.com");
  svetlana->AddReport("Andre", "andre@example.com");

  // Good thing Svetlana just hired, here are a bunch of tasks.
  svetlana->AddTask("INFRA-102", "Bring up new datacenter")->SetCompletion(.75);
  svetlana->AddTask("INFRA-103", "Cleanup old file structure")
      ->SetCompletion(.25);
  svetlana->AddTask("INFRA-104", "Rewire the datacenter again")
      ->SetCompletion(.9);
  svetlana->AddTask("INFRA-105", "Upgrade the cooling system")
      ->SetCompletion(.8);
  svetlana->AddTask("INFRA-106", "Investigate opening a datacenter on Mars")
      ->SetCompletion(1);
  svetlana->AddTask("INFRA-107", "Interface with the cloud")
      ->SetCompletion(.05);

  loop.Run();
  return 0;
}
