// Copyright 2018 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/bin/sessionmgr/story/model/story_model_owner.h"

#include <lib/fit/bridge.h>
#include <lib/fit/defer.h>
#include <lib/fxl/logging.h>
#include "peridot/bin/sessionmgr/story/model/apply_mutations.h"
#include "peridot/bin/sessionmgr/story/model/story_model_storage.h"
#include "peridot/bin/sessionmgr/story/model/story_mutator.h"

using fuchsia::modular::storymodel::ModuleModel;
using fuchsia::modular::storymodel::StoryModel;
using fuchsia::modular::storymodel::StoryModelMutation;

namespace modular {

namespace {
// Sets default values for all fields of a new StoryModel. Defaults are
// documented in
// peridot/lib/fidl/public/fuchsia.modular.storymodel/story_model.fidl.
void InitializeModelDefaults(StoryModel* model) {
  model->set_runtime_state(fuchsia::modular::StoryState::STOPPED);
  model->set_visibility_state(fuchsia::modular::StoryVisibilityState::DEFAULT);
  model->set_modules({});
}
}  // namespace

// Delegates Execute() to the StoryModelOwner.
class StoryModelOwner::Mutator : public StoryMutator {
 public:
  Mutator(fxl::WeakPtr<StoryModelOwner> weak_owner) : weak_owner_(weak_owner) {}
  ~Mutator() override = default;

 private:
  // |StoryMutator|
  fit::consumer<> ExecuteInternal(
      std::vector<StoryModelMutation> commands) override {
    if (!weak_owner_) {
      fit::bridge<> bridge;
      bridge.completer.complete_error();
      return std::move(bridge.consumer);
    }
    return weak_owner_->ExecuteCommands(std::move(commands));
  }

  fxl::WeakPtr<StoryModelOwner> weak_owner_;
};

// Manages the lifecycle of multiple listener callbacks. When Observer dies,
// all callbacks registered with RegisterListener() are unregistered from the
// backing StoryModelOwner.
class StoryModelOwner::Observer : public StoryObserver {
 public:
  Observer(fxl::WeakPtr<StoryModelOwner> weak_owner)
      : weak_owner_(weak_owner) {}
  ~Observer() {
    // If our owner is gone, all of the listener functions have already been
    // cleaned up. We need to cancel all the deferred actions since they
    // capture and make a call on our owner.
    if (!weak_owner_) {
      for (auto& i : deferred_cleanup_) {
        i.cancel();
      }
    }
  }

 private:
  void RegisterListener(
      fit::function<void(const StoryModel&)> listener) override {
    if (!weak_owner_) {
      return;
      // |listener| is destroyed.
    }

    deferred_cleanup_.push_back(
        weak_owner_->RegisterListener(std::move(listener)));
  }

  const StoryModel& model() override {
    FXL_CHECK(weak_owner_);
    return weak_owner_->model_;
  }

  fxl::WeakPtr<StoryModelOwner> weak_owner_;
  // When we are destroyed, we want to clean up any listeners we've added to
  // |shared_state_->owner|.
  std::vector<fit::deferred_action<fit::function<void()>>> deferred_cleanup_;
};

StoryModelOwner::StoryModelOwner(
    const std::string& story_name, fit::executor* executor,
    std::unique_ptr<StoryModelStorage> model_storage)
    : model_storage_(std::move(model_storage)),
      weak_ptr_factory_(this),
      executor_(executor) {
  FXL_CHECK(model_storage_ != nullptr);
  model_.mutable_name()->assign(story_name);
  InitializeModelDefaults(&model_);
  model_storage_->SetObserveCallback(
      [this](std::vector<StoryModelMutation> commands) {
        HandleObservedMutations(std::move(commands));
      });
}

StoryModelOwner::~StoryModelOwner() = default;

std::unique_ptr<StoryMutator> StoryModelOwner::NewMutator() {
  return std::make_unique<Mutator>(weak_ptr_factory_.GetWeakPtr());
}

std::unique_ptr<StoryObserver> StoryModelOwner::NewObserver() {
  return std::make_unique<Observer>(weak_ptr_factory_.GetWeakPtr());
}

void StoryModelOwner::LoadStorage() {
  FXL_CHECK(!seen_any_requests_to_execute_)
      << "Must call LoadStorage() before any calls to StoryMutator.Execute();";
  executor_->schedule_task(model_storage_->Load());
}

fit::consumer<> StoryModelOwner::FlushStorage() {
  fit::bridge<> bridge;
  executor_->schedule_task(model_storage_->Flush().then(
      [completer = std::move(bridge.completer)](fit::result<>& result) mutable {
        if (result.is_ok()) {
          completer.complete_ok();
        } else {
          completer.complete_error();
        }
      }));
  return std::move(bridge.consumer);
}

fit::deferred_action<fit::function<void()>> StoryModelOwner::RegisterListener(
    fit::function<void(const StoryModel&)> listener) {
  auto it = listeners_.insert(listeners_.end(), std::move(listener));
  return fit::defer(
      fit::function<void()>([this, it] { listeners_.erase(it); }));
}

fit::consumer<> StoryModelOwner::ExecuteCommands(
    std::vector<StoryModelMutation> commands) {
  seen_any_requests_to_execute_ = true;
  // fit::bridge allows this function to return (and eventually complete) a
  // promise that is owned by the caller and still schedule a promise as a task
  // to execute the model update locally.
  //
  // If the caller chooses to ignore the result, our local promise will still be
  // scheduled and executed.
  fit::bridge<> bridge;
  auto promise = model_storage_->Execute(std::move(commands))
                     .then([completer = std::move(bridge.completer)](
                               fit::result<>& result) mutable {
                       if (result.is_ok()) {
                         completer.complete_ok();
                       } else {
                         completer.complete_error();
                       }
                     });

  executor_->schedule_task(std::move(promise));
  return std::move(bridge.consumer);
}

void StoryModelOwner::HandleObservedMutations(
    std::vector<StoryModelMutation> commands) {
  // This is not thread-safe. We rely on the fact that
  // HandleObservedMutations() will only be called on a single thread.
  StoryModel old_model;
  FXL_CHECK(fidl::Clone(model_, &old_model) == ZX_OK);
  model_ = ApplyMutations(old_model, std::move(commands));

  // Don't notify anyone if the model didn't change.
  if (model_ == old_model) {
    return;
  }

  executor_->schedule_task(fit::make_promise([this] {
                             for (auto& listener : listeners_) {
                               listener(model_);
                             }
                             return fit::ok();
                           }).wrap_with(scope_));
}

}  // namespace modular
