// 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_mutator.h"
#include "peridot/bin/sessionmgr/story/model/story_model_storage.h"

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

namespace modular {

namespace {
// Sets default values for all fields of a new StoryModel.
void InitializeModelDefaults(StoryModel* model) {
  model->set_visibility_state(fuchsia::modular::StoryVisibilityState::DEFAULT);
  model->set_modules(fidl::VectorPtr<ModuleModel>::New(0));
}
}  // 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()->reset(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());
}

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) {
  // 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
