// 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 <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <iostream>

#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 <lib/fxl/functional/make_copyable.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/string_printf.h>
#include <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()));
}

std::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();
  };
}

std::function<void(fuchsia::ledger::Status)> HandleResponse(
    fit::closure quit_callback, std::string description) {
  return [description, &quit_callback](fuchsia::ledger::Status status) {
    if (status != fuchsia::ledger::Status::OK) {
      FXL_LOG(ERROR) << description << " failed";
      quit_callback();
    }
  };
}

void GetEntries(fuchsia::ledger::PageSnapshotPtr snapshot,
                std::vector<fuchsia::ledger::Entry> entries,
                std::unique_ptr<fuchsia::ledger::Token> token,
                std::function<void(fuchsia::ledger::Status,
                                   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),
      fxl::MakeCopyable(
          [snapshot = std::move(snapshot), entries = std::move(entries),
           callback = std::move(callback)](fuchsia::ledger::Status status,
                                           auto new_entries,
                                           auto next_token) mutable {
            if (status != fuchsia::ledger::Status::OK &&
                status != fuchsia::ledger::Status::PARTIAL_RESULT) {
              callback(status, {});
              return;
            }
            for (size_t i = 0; i < new_entries.size(); ++i) {
              entries.push_back(std::move(new_entries.at(i)));
            }
            if (status == fuchsia::ledger::Status::OK) {
              callback(fuchsia::ledger::Status::OK, std::move(entries));
              return;
            }
            GetEntries(std::move(snapshot), std::move(entries),
                       std::move(next_token), std::move(callback));
          }));
}

void GetEntries(fuchsia::ledger::PageSnapshotPtr snapshot,
                std::function<void(fuchsia::ledger::Status,
                                   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(),
      HandleResponse([this] { loop_->Quit(); }, "GetRootPage"));

  fuchsia::ledger::PageSnapshotPtr snapshot;
  page_->GetSnapshot(snapshot.NewRequest(), fidl::VectorPtr<uint8_t>::New(0),
                     page_watcher_binding_.NewBinding(),
                     HandleResponse([this] { loop_->Quit(); }, "Watch"));
  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),
             [this](fuchsia::ledger::Status status, auto entries) {
               if (status != fuchsia::ledger::Status::OK) {
                 FXL_LOG(ERROR) << "GetEntries failed";
                 loop_->Quit();
                 return;
               }

               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(std::function<void(std::vector<Key>)> callback) {
  fuchsia::ledger::PageSnapshotPtr snapshot;
  page_->GetSnapshot(snapshot.NewRequest(), {}, nullptr,
                     HandleResponse([this] { loop_->Quit(); }, "GetSnapshot"));

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

void TodoApp::AddNew() {
  page_->Put(MakeKey(), ToArray(generator_.Generate()),
             HandleResponse([this] { loop_->Quit(); }, "Put"));
}

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_))),
                HandleResponse([this] { loop_->Quit(); }, "Delete"));
}

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;
}
