// Copyright 2016 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 "peridot/examples/todo_cpp/todo.h"

#include <fuchsia/ledger/internal/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/component/cpp/connect.h>
#include <lib/fit/function.h>
#include <lib/fsl/vmo/strings.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <algorithm>
#include <iostream>

#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/fxl/time/time_delta.h"

namespace todo {

namespace {

const double kMeanListSize = 7.0;
const double kListSizeStdDev = 2.0;
const int kMinDelaySeconds = 1;
const int kMaxDelaySeconds = 5;

std::string ToString(const fuchsia::mem::Buffer& vmo) {
  std::string ret;
  if (!fsl::StringFromVmo(vmo, &ret)) {
    FXL_DCHECK(false);
  }
  return ret;
}

fidl::VectorPtr<uint8_t> ToArray(const std::string& val) {
  auto ret = fidl::VectorPtr<uint8_t>::New(val.size());
  memcpy(ret->data(), val.data(), val.size());
  return ret;
}

Key MakeKey() {
  return ToArray(fxl::StringPrintf("%120ld-%u", time(nullptr), rand()));
}

fit::function<void(zx_status_t)> NewErrorHandler(fit::closure quit_callback,
                                                 std::string description) {
  return [description, &quit_callback](zx_status_t status) {
    FXL_LOG(ERROR) << description << " diconnected: " << status;
    quit_callback();
  };
}

void GetEntries(
    fuchsia::ledger::PageSnapshotPtr snapshot,
    std::vector<fuchsia::ledger::Entry> entries,
    std::unique_ptr<fuchsia::ledger::Token> token,
    fit::function<void(std::vector<fuchsia::ledger::Entry>)> callback) {
  fuchsia::ledger::PageSnapshot* snapshot_ptr = snapshot.get();
  snapshot_ptr->GetEntries(
      fidl::VectorPtr<uint8_t>::New(0), std::move(token),
      [snapshot = std::move(snapshot), entries = std::move(entries),
       callback = std::move(callback)](fuchsia::ledger::IterationStatus status,
                                       auto new_entries,
                                       auto next_token) mutable {
        for (size_t i = 0; i < new_entries.size(); ++i) {
          entries.push_back(std::move(new_entries.at(i)));
        }
        if (status == fuchsia::ledger::IterationStatus::OK) {
          callback(std::move(entries));
          return;
        }
        GetEntries(std::move(snapshot), std::move(entries),
                   std::move(next_token), std::move(callback));
      });
}

void GetEntries(
    fuchsia::ledger::PageSnapshotPtr snapshot,
    fit::function<void(std::vector<fuchsia::ledger::Entry>)> callback) {
  GetEntries(std::move(snapshot), {}, nullptr, std::move(callback));
}

}  // namespace

TodoApp::TodoApp(async::Loop* loop)
    : loop_(loop),
      rng_(time(nullptr)),
      size_distribution_(kMeanListSize, kListSizeStdDev),
      delay_distribution_(kMinDelaySeconds, kMaxDelaySeconds),
      generator_(&rng_),
      context_(component::StartupContext::CreateFromStartupInfo()),
      page_watcher_binding_(this) {
  context_->ConnectToEnvironmentService(module_context_.NewRequest());
  module_context_->GetComponentContext(component_context_.NewRequest());
  ledger_.set_error_handler(
      NewErrorHandler([this] { loop_->Quit(); }, "Ledger"));
  component_context_->GetLedger(ledger_.NewRequest());
  ledger_->GetRootPage(page_.NewRequest());

  fuchsia::ledger::PageSnapshotPtr snapshot;
  page_->GetSnapshot(snapshot.NewRequest(), fidl::VectorPtr<uint8_t>::New(0),
                     page_watcher_binding_.NewBinding());
  List(std::move(snapshot));

  async::PostTask(loop_->dispatcher(), [this] { Act(); });
}

void TodoApp::Terminate() { loop_->Quit(); }

void TodoApp::OnChange(fuchsia::ledger::PageChange /*page_change*/,
                       fuchsia::ledger::ResultState result_state,
                       OnChangeCallback callback) {
  if (result_state != fuchsia::ledger::ResultState::PARTIAL_STARTED &&
      result_state != fuchsia::ledger::ResultState::COMPLETED) {
    // Only request the entries list once, on the first OnChange call.
    callback(nullptr);
    return;
  }

  fuchsia::ledger::PageSnapshotPtr snapshot;
  callback(snapshot.NewRequest());
  List(std::move(snapshot));
}

void TodoApp::List(fuchsia::ledger::PageSnapshotPtr snapshot) {
  GetEntries(std::move(snapshot), [](auto entries) {
    std::cout << "--- To Do ---" << std::endl;
    for (auto& entry : entries) {
      std::cout << (entry.value ? ToString(*entry.value) : "<empty>")
                << std::endl;
    }
    std::cout << "---" << std::endl;
  });
}

void TodoApp::GetKeys(fit::function<void(std::vector<Key>)> callback) {
  fuchsia::ledger::PageSnapshotPtr snapshot;
  page_->GetSnapshot(snapshot.NewRequest(), {}, nullptr);

  fuchsia::ledger::PageSnapshot* snapshot_ptr = snapshot.get();
  snapshot_ptr->GetKeys(
      {}, nullptr,
      [snapshot = std::move(snapshot), callback = std::move(callback)](
          fuchsia::ledger::IterationStatus status, auto keys, auto next_token) {
        callback(std::move(keys));
      });
}

void TodoApp::AddNew() {
  page_->Put(MakeKey(), ToArray(generator_.Generate()));
}

void TodoApp::DeleteOne(std::vector<Key> keys) {
  FXL_DCHECK(keys.size());
  std::uniform_int_distribution<> distribution(0, keys.size() - 1);
  page_->Delete(std::move(keys.at(distribution(rng_))));
}

void TodoApp::Act() {
  GetKeys([this](std::vector<Key> keys) {
    size_t target_size = std::round(size_distribution_(rng_));
    if (keys.size() > std::max(static_cast<size_t>(0), target_size)) {
      DeleteOne(std::move(keys));
    } else {
      AddNew();
    }
  });
  zx::duration delay = zx::sec(delay_distribution_(rng_));
  async::PostDelayedTask(
      loop_->dispatcher(), [this] { Act(); }, delay);
}

}  // namespace todo

int main(int /*argc*/, const char** /*argv*/) {
  async::Loop loop(&kAsyncLoopConfigAttachToThread);
  todo::TodoApp app(&loop);
  loop.Run();
  return 0;
}
