// 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/bin/suggestion_engine/suggestion_engine_impl.h"

#include <string>

#include <fuchsia/modular/cpp/fidl.h>
#include <lib/context/cpp/context_helper.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/functional/make_copyable.h>
#include <lib/fxl/time/time_delta.h>
#include <lib/fxl/time/time_point.h>
#include "lib/fidl/cpp/clone.h"

#include "peridot/bin/suggestion_engine/auto_select_first_query_listener.h"
#include "peridot/bin/suggestion_engine/decision_policies/rank_over_threshold_decision_policy.h"
#include "peridot/bin/suggestion_engine/filters/conjugate_ranked_passive_filter.h"
#include "peridot/bin/suggestion_engine/filters/ranked_active_filter.h"
#include "peridot/bin/suggestion_engine/filters/ranked_passive_filter.h"
#include "peridot/bin/suggestion_engine/rankers/linear_ranker.h"
#include "peridot/bin/suggestion_engine/ranking_features/annoyance_ranking_feature.h"
#include "peridot/bin/suggestion_engine/ranking_features/dead_story_ranking_feature.h"
#include "peridot/bin/suggestion_engine/ranking_features/focused_story_ranking_feature.h"
#include "peridot/bin/suggestion_engine/ranking_features/interrupting_ranking_feature.h"
#include "peridot/bin/suggestion_engine/ranking_features/kronk_ranking_feature.h"
#include "peridot/bin/suggestion_engine/ranking_features/mod_pair_ranking_feature.h"
#include "peridot/bin/suggestion_engine/ranking_features/proposal_hint_ranking_feature.h"
#include "peridot/bin/suggestion_engine/ranking_features/query_match_ranking_feature.h"
#include "peridot/bin/suggestion_engine/ranking_features/ranking_feature.h"
#include "peridot/lib/fidl/json_xdr.h"

namespace modular {

std::string StoryNameKey(const std::string& source_url,
                         const std::string& story_name) {
  return source_url + story_name;
}

namespace {

constexpr int kQueryActionMaxResults = 1;

}  // namespace

SuggestionEngineImpl::SuggestionEngineImpl(fuchsia::media::AudioPtr audio)
    : debug_(std::make_shared<SuggestionDebugImpl>()),
      next_processor_(debug_),
      query_processor_(std::move(audio), debug_),
      context_listener_binding_(this),
      auto_select_first_query_listener_(this),
      auto_select_first_query_listener_binding_(
          &auto_select_first_query_listener_) {}

SuggestionEngineImpl::~SuggestionEngineImpl() = default;

fxl::WeakPtr<SuggestionDebugImpl> SuggestionEngineImpl::debug() {
  return debug_->GetWeakPtr();
}

void SuggestionEngineImpl::AddNextProposal(
    ProposalPublisherImpl* source, fuchsia::modular::Proposal proposal) {
  if (proposal.wants_rich_suggestion &&
      CanComponentUseRichSuggestions(source->component_url())) {
    AddProposalWithRichSuggestion(source, std::move(proposal));
  } else {
    auto story_id =
        StoryIdFromName(source->component_url(), proposal.story_name);
    next_processor_.AddProposal(source->component_url(), story_id,
                                std::move(proposal));
  }
}

void SuggestionEngineImpl::ProposeNavigation(
    const fuchsia::modular::NavigationAction navigation) {
  navigation_processor_.Navigate(navigation);
}

void SuggestionEngineImpl::AddProposalWithRichSuggestion(
    ProposalPublisherImpl* source, fuchsia::modular::Proposal proposal) {
  auto activity = debug_->GetIdleWaiter()->RegisterOngoingActivity();
  fuchsia::modular::StoryOptions story_options;
  story_options.kind_of_proto_story = true;
  story_provider_->CreateStoryWithOptions(
      std::move(story_options),
      fxl::MakeCopyable([this, proposal = std::move(proposal),
                         source_url = source->component_url(),
                         activity](fidl::StringPtr preloaded_story_id) mutable {
        auto story_id = StoryIdFromName(source_url, proposal.story_name);
        ExecuteActions(std::move(proposal.on_selected),
                       nullptr /* proposal_listener */, proposal.id,
                       preloaded_story_id);
        next_processor_.AddProposal(source_url, story_id, preloaded_story_id,
                                    std::move(proposal));
      }));
}

void SuggestionEngineImpl::RemoveNextProposal(const std::string& component_url,
                                              const std::string& proposal_id) {
  SuggestionPrototype* suggestion =
      next_processor_.GetSuggestion(component_url, proposal_id);
  if (suggestion && !suggestion->preloaded_story_id.empty()) {
    story_provider_->DeleteStory(suggestion->preloaded_story_id, [] {});
  }
  next_processor_.RemoveProposal(component_url, proposal_id);
}

void SuggestionEngineImpl::PromoteNextProposal(
    const std::string& component_url, const std::string& preloaded_story_id,
    const std::string& proposal_id) {
  auto activity = debug_->GetIdleWaiter()->RegisterOngoingActivity();
  story_provider_->SetKindOfProtoStoryOption(preloaded_story_id, false,
                                             [activity]() {});
  next_processor_.RemoveProposal(component_url, proposal_id);
}

void SuggestionEngineImpl::Connect(
    fidl::InterfaceRequest<fuchsia::modular::SuggestionEngine> request) {
  bindings_.AddBinding(this, std::move(request));
}

void SuggestionEngineImpl::Connect(
    fidl::InterfaceRequest<fuchsia::modular::SuggestionProvider> request) {
  suggestion_provider_bindings_.AddBinding(this, std::move(request));
}

void SuggestionEngineImpl::Connect(
    fidl::InterfaceRequest<fuchsia::modular::SuggestionDebug> request) {
  debug_bindings_.AddBinding(debug_.get(), std::move(request));
}

// |fuchsia::modular::SuggestionProvider|
void SuggestionEngineImpl::Query(
    fidl::InterfaceHandle<fuchsia::modular::QueryListener> listener,
    fuchsia::modular::UserInput input, int count) {
  query_processor_.ExecuteQuery(std::move(input), count, std::move(listener));
}

// |fuchsia::modular::SuggestionProvider|
void SuggestionEngineImpl::SubscribeToInterruptions(
    fidl::InterfaceHandle<fuchsia::modular::InterruptionListener> listener) {
  next_processor_.RegisterInterruptionListener(std::move(listener));
}

// |fuchsia::modular::SuggestionProvider|
void SuggestionEngineImpl::SubscribeToNavigation(
    fidl::InterfaceHandle<fuchsia::modular::NavigationListener> listener) {
  navigation_processor_.RegisterListener(std::move(listener));
}

// |fuchsia::modular::SuggestionProvider|
void SuggestionEngineImpl::SubscribeToNext(
    fidl::InterfaceHandle<fuchsia::modular::NextListener> listener, int count) {
  next_processor_.RegisterListener(std::move(listener), count);
}

// |fuchsia::modular::SuggestionProvider|
void SuggestionEngineImpl::RegisterFeedbackListener(
    fidl::InterfaceHandle<fuchsia::modular::FeedbackListener> speech_listener) {
  query_processor_.RegisterFeedbackListener(std::move(speech_listener));
}

// |fuchsia::modular::SuggestionProvider|
void SuggestionEngineImpl::NotifyInteraction(
    fidl::StringPtr suggestion_uuid,
    fuchsia::modular::Interaction interaction) {
  // Find the suggestion
  bool suggestion_in_ask = false;
  RankedSuggestion* suggestion = next_processor_.GetSuggestion(suggestion_uuid);
  if (!suggestion) {
    suggestion = query_processor_.GetSuggestion(suggestion_uuid);
    suggestion_in_ask = true;
  }

  // If it exists (and it should), perform the action and clean up
  if (suggestion) {
    auto component_url = suggestion->prototype->source_url;
    std::string log_detail = suggestion->prototype
                                 ? short_proposal_str(*suggestion->prototype)
                                 : "invalid";

    FXL_LOG(INFO) << (interaction.type ==
                              fuchsia::modular::InteractionType::SELECTED
                          ? "Accepted"
                          : "Dismissed")
                  << " suggestion " << suggestion_uuid << " (" << log_detail
                  << ")";

    debug_->OnSuggestionSelected(suggestion->prototype);

    auto& proposal = suggestion->prototype->proposal;
    auto proposal_id = proposal.id;
    auto preloaded_story_id = suggestion->prototype->preloaded_story_id;
    suggestion->interrupting = false;
    switch (interaction.type) {
      case fuchsia::modular::InteractionType::SELECTED: {
        if (!preloaded_story_id.empty()) {
          // Notify before we promote + remove from next since the proposal
          // won't be available when that happens.
          if (proposal.listener) {
            auto listener = proposal.listener.Bind();
            listener->OnProposalAccepted(proposal.id, preloaded_story_id);
          }
          PromoteNextProposal(component_url, preloaded_story_id, proposal_id);
          // Only next suggestions can be rich so we can finish early.
          // No need to remove.
          return;
        }
        PerformActions(std::move(proposal.on_selected),
                       std::move(proposal.listener), proposal.id,
                       proposal.story_name, component_url, proposal.story_id);
        break;
      }
      case fuchsia::modular::InteractionType::DISMISSED: {
        break;  // Remove suggestion since it was dismissed by user.
      }
      // These actions .
      case fuchsia::modular::InteractionType::EXPIRED:
      case fuchsia::modular::InteractionType::SNOOZED: {
        // No need to remove since it was either expired by a timeout in
        // user shell or snoozed by the user.
        return;
      }
    }

    if (suggestion_in_ask) {
      query_processor_.CleanUpPreviousQuery();
    } else {
      RemoveNextProposal(component_url, proposal_id);
    }
  } else {
    FXL_LOG(WARNING) << "Requested suggestion prototype not found. UUID: "
                     << suggestion_uuid;
  }
}

// |fuchsia::modular::SuggestionEngine|
void SuggestionEngineImpl::RegisterProposalPublisher(
    fidl::StringPtr url,
    fidl::InterfaceRequest<fuchsia::modular::ProposalPublisher> publisher) {
  // Check to see if a fuchsia::modular::ProposalPublisher has already been
  // created for the component with this url. If not, create one.
  std::unique_ptr<ProposalPublisherImpl>& source = proposal_publishers_[url];
  if (!source) {  // create if it didn't already exist
    source = std::make_unique<ProposalPublisherImpl>(this, url);
  }

  source->AddBinding(std::move(publisher));
}

// |fuchsia::modular::SuggestionEngine|
void SuggestionEngineImpl::RegisterQueryHandler(
    fidl::StringPtr url, fidl::InterfaceHandle<fuchsia::modular::QueryHandler>
                             query_handler_handle) {
  query_processor_.RegisterQueryHandler(url, std::move(query_handler_handle));
}

// |fuchsia::modular::SuggestionEngine|
void SuggestionEngineImpl::Initialize(
    fidl::InterfaceHandle<fuchsia::modular::StoryProvider> story_provider,
    fidl::InterfaceHandle<fuchsia::modular::FocusProvider> focus_provider,
    fidl::InterfaceHandle<fuchsia::modular::ContextWriter> context_writer,
    fidl::InterfaceHandle<fuchsia::modular::ContextReader> context_reader,
    fidl::InterfaceHandle<fuchsia::modular::PuppetMaster> puppet_master) {
  story_provider_.Bind(std::move(story_provider));
  focus_provider_ptr_.Bind(std::move(focus_provider));
  context_reader_.Bind(std::move(context_reader));
  query_processor_.Initialize(std::move(context_writer));
  puppet_master_.Bind(std::move(puppet_master));
  RegisterRankingFeatures();
}

// end fuchsia::modular::SuggestionEngine

void SuggestionEngineImpl::RegisterRankingFeatures() {
  // Create common ranking features
  ranking_features["proposal_hint_rf"] =
      std::make_shared<ProposalHintRankingFeature>();
  ranking_features["kronk_rf"] = std::make_shared<KronkRankingFeature>();
  ranking_features["mod_pairs_rf"] = std::make_shared<ModPairRankingFeature>();
  ranking_features["query_match_rf"] =
      std::make_shared<QueryMatchRankingFeature>();
  ranking_features["focused_story_rf"] =
      std::make_shared<FocusedStoryRankingFeature>();
  ranking_features["annoyance_rf"] =
      std::make_shared<AnnoyanceRankingFeature>();
  ranking_features["dead_story_rf"] =
      std::make_shared<DeadStoryRankingFeature>();
  ranking_features["is_interrupting_rf"] =
      std::make_shared<InterruptingRankingFeature>();

  // Get context updates every time a story is focused to rerank suggestions
  // based on the story that is focused at the moment.
  fuchsia::modular::ContextQuery query;
  for (auto const& it : ranking_features) {
    fuchsia::modular::ContextSelectorPtr selector =
        it.second->CreateContextSelector();
    if (selector) {
      AddToContextQuery(&query, it.first, std::move(*selector));
    }
  }
  context_reader_->Subscribe(std::move(query),
                             context_listener_binding_.NewBinding());

  // TODO(jwnichols): Replace the code configuration of the ranking features
  // with a configuration file

  // Set up the next ranking features
  auto next_ranker = std::make_unique<LinearRanker>();
  next_ranker->AddRankingFeature(1.0, ranking_features["proposal_hint_rf"]);
  next_ranker->AddRankingFeature(-0.1, ranking_features["kronk_rf"]);
  next_ranker->AddRankingFeature(0, ranking_features["mod_pairs_rf"]);
  next_ranker->AddRankingFeature(1.0, ranking_features["focused_story_rf"]);
  next_processor_.SetRanker(std::move(next_ranker));

  // Set up the query ranking features
  auto query_ranker = std::make_unique<LinearRanker>();
  query_ranker->AddRankingFeature(1.0, ranking_features["proposal_hint_rf"]);
  query_ranker->AddRankingFeature(-0.1, ranking_features["kronk_rf"]);
  query_ranker->AddRankingFeature(0, ranking_features["mod_pairs_rf"]);
  query_ranker->AddRankingFeature(0, ranking_features["query_match_rf"]);
  query_processor_.SetRanker(std::move(query_ranker));

  // Set up the interrupt ranking features
  auto interrupt_ranker = std::make_unique<LinearRanker>();
  interrupt_ranker->AddRankingFeature(1.0, ranking_features["annoyance_rf"]);
  auto decision_policy = std::make_unique<RankOverThresholdDecisionPolicy>(
      std::move(interrupt_ranker));
  next_processor_.SetInterruptionDecisionPolicy(std::move(decision_policy));

  // Set up passive filters
  std::vector<std::unique_ptr<SuggestionPassiveFilter>> passive_filters;
  passive_filters.push_back(std::make_unique<ConjugateRankedPassiveFilter>(
      ranking_features["focused_story_rf"]));
  passive_filters.push_back(std::make_unique<RankedPassiveFilter>(
      ranking_features["is_interrupting_rf"]));
  next_processor_.SetPassiveFilters(std::move(passive_filters));
}

void SuggestionEngineImpl::PerformActions(
    fidl::VectorPtr<fuchsia::modular::Action> actions,
    fidl::InterfaceHandle<fuchsia::modular::ProposalListener> listener,
    const std::string& proposal_id, const std::string& story_name,
    const std::string& source_url, const std::string& proposal_story_id) {
  if (story_name.empty()) {
    ExecuteActions(std::move(actions), std::move(listener), proposal_id,
                   proposal_story_id);
    return;
  }
  const std::string key = StoryNameKey(source_url, story_name);
  auto it = story_name_mapping_.find(key);
  if (it == story_name_mapping_.end()) {
    story_provider_->CreateStory(
        nullptr /* module_url */,
        fxl::MakeCopyable([this, actions = std::move(actions),
                           listener = std::move(listener), proposal_id,
                           story_name, source_url](
                              const fidl::StringPtr& story_id) mutable {
          story_name_mapping_[StoryNameKey(source_url, story_name)] = story_id;
          // TODO(miguelfrde): better expect clients to send focus action?
          focus_provider_ptr_->Request(story_id);
          ExecuteActions(std::move(actions), std::move(listener), proposal_id,
                         story_id);
        }));
  } else {
    ExecuteActions(std::move(actions), std::move(listener), proposal_id,
                   it->second);
  }
}

void SuggestionEngineImpl::ExecuteActions(
    fidl::VectorPtr<fuchsia::modular::Action> actions,
    fidl::InterfaceHandle<fuchsia::modular::ProposalListener> listener,
    const std::string& proposal_id, const std::string& override_story_id) {
  for (auto& action : *actions) {
    switch (action.Which()) {
      // TODO(miguelfrde): CreateStory is deprecated, remove.
      case fuchsia::modular::Action::Tag::kCreateStory: {
        // If we are overriding a story, no need to create a new story. Ignore
        // this action.
        if (override_story_id.empty()) {
          PerformCreateStoryAction(action, std::move(listener), proposal_id);
        } else {
          FXL_LOG(INFO) << "Ignored CreateStory action since we are overriding "
                        << " a story.";
        }
        break;
      }
      case fuchsia::modular::Action::Tag::kFocusStory: {
        PerformFocusStoryAction(action, override_story_id);
        break;
      }
      case fuchsia::modular::Action::Tag::kFocusModule: {
        PerformFocusModuleAction(action, override_story_id);
        break;
      }
      case fuchsia::modular::Action::Tag::kAddModule: {
        PerformAddModuleAction(action, std::move(listener), proposal_id,
                               override_story_id);
        break;
      }
      case fuchsia::modular::Action::Tag::kQueryAction: {
        PerformQueryAction(action);
        break;
      }
      case fuchsia::modular::Action::Tag::kSetLinkValueAction: {
        PerformSetLinkValueAction(action, override_story_id);
        break;
      }
      case fuchsia::modular::Action::Tag::kUpdateModule: {
        PerformUpdateModuleAction(&action, override_story_id);
        break;
      }
      case fuchsia::modular::Action::Tag::kCustomAction: {
        PerformCustomAction(&action);
        break;
      }
      default:
        FXL_LOG(WARNING) << "Unknown action tag " << (uint32_t)action.Which();
    }
  }

  if (listener) {
    auto proposal_listener = listener.Bind();
    proposal_listener->OnProposalAccepted(proposal_id, override_story_id);
  }
}

void SuggestionEngineImpl::PerformCreateStoryAction(
    const fuchsia::modular::Action& action,
    fidl::InterfaceHandle<fuchsia::modular::ProposalListener> listener,
    const std::string& proposal_id) {
  auto activity = debug_->GetIdleWaiter()->RegisterOngoingActivity();
  auto& create_story = action.create_story();

  if (!story_provider_) {
    FXL_LOG(WARNING) << "Unable to add module; no story provider";
    return;
  }

  fuchsia::modular::Intent intent;
  create_story.intent.Clone(&intent);

  if (intent.handler) {
    FXL_LOG(INFO) << "Creating story with module " << intent.handler;
  } else {  // intent.action
    FXL_LOG(INFO) << "Creating story with action " << intent.action;
  }

  story_provider_->CreateStory(
      nullptr /* module_url */,
      fxl::MakeCopyable([this, listener = std::move(listener), proposal_id,
                         intent = std::move(intent),
                         activity](const fidl::StringPtr& story_id) mutable {
        fuchsia::modular::StoryControllerPtr story_controller;
        story_provider_->GetController(story_id, story_controller.NewRequest());
        // TODO(thatguy): We give the first module the name "root". We'd like to
        // move away from module names being assigned by the framework or other
        // components, and rather have clients always provide a module name.
        story_controller->AddModule(nullptr /* parent module path */,
                                    "root" /* module name */, std::move(intent),
                                    nullptr /* surface relation */);
        focus_provider_ptr_->Request(story_id);

        if (listener) {
          auto proposal_listener = listener.Bind();
          proposal_listener->OnProposalAccepted(proposal_id, story_id);
        }
      }));
}

void SuggestionEngineImpl::PerformFocusStoryAction(
    const fuchsia::modular::Action& action,
    const std::string& override_story_id) {
  const auto& focus_story = action.focus_story();
  std::string story_id = focus_story.story_id;
  if (!override_story_id.empty()) {
    story_id = override_story_id;
    if (override_story_id != focus_story.story_id) {
      FXL_LOG(WARNING)
          << "story_id provided on fuchsia::modular::Proposal ("
          << override_story_id
          << ") does not match that on fuchsia::modular::FocusStory action ("
          << focus_story.story_id << "). Using " << override_story_id << ".";
    }
  }
  FXL_LOG(INFO) << "Requesting focus for story_id " << story_id;
  focus_provider_ptr_->Request(story_id);
}

void SuggestionEngineImpl::PerformFocusModuleAction(
    const fuchsia::modular::Action& action, const std::string& story_id) {
  if (story_id.empty()) {
    FXL_LOG(WARNING) << "Unable to focus module; no story id provided";
    return;
  }
  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider_->GetController(story_id, story_controller.NewRequest());
  auto module_path = action.focus_module().module_path.Clone();
  if (module_path->empty()) {
    FXL_LOG(WARNING) << "Unable to focus module; no module path provided";
    return;
  }

  fuchsia::modular::ModuleControllerPtr mod_controller;
  story_controller->GetModuleController(std::move(module_path),
                                        mod_controller.NewRequest());
  mod_controller->Focus();
}

void SuggestionEngineImpl::PerformAddModuleAction(
    const fuchsia::modular::Action& action,
    fidl::InterfaceHandle<fuchsia::modular::ProposalListener> listener,
    const std::string& proposal_id, const std::string& override_story_id) {
  if (!story_provider_) {
    FXL_LOG(WARNING) << "Unable to add module; no story provider";
    return;
  }
  const auto& add_module = action.add_module();
  const auto& module_name = add_module.module_name;
  std::string story_id = add_module.story_id;

  if (!override_story_id.empty()) {
    story_id = override_story_id;
    if (!add_module.story_id->empty() &&
        override_story_id != add_module.story_id) {
      FXL_LOG(WARNING)
          << "story_id provided on fuchsia::modular::Proposal ("
          << override_story_id
          << ") does not match that on fuchsia::modular::AddModule action ("
          << add_module.story_id << "). Using " << override_story_id << ".";
    }
  }

  FXL_CHECK(!story_id.empty())
      << "Attempting to add module without specifying a story id.";

  auto parent_module_path = add_module.surface_parent_module_path.Clone();

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider_->GetController(story_id, story_controller.NewRequest());
  fuchsia::modular::Intent intent;
  fidl::Clone(add_module.intent, &intent);
  story_controller->AddModule(parent_module_path.Clone(), module_name,
                              std::move(intent),
                              fidl::MakeOptional(add_module.surface_relation));

  // Focus the added module.
  parent_module_path.push_back(module_name);
  fuchsia::modular::ModuleControllerPtr mod_controller;
  story_controller->GetModuleController(std::move(parent_module_path),
                                        mod_controller.NewRequest());
  mod_controller->Focus();

  //  Notify with story id where the mod was added. This notifications will be
  //  done in a central place once the refactor into puppet master is completed.
  //  For now we notify here to be able to send the right story id in which the
  //  mod was added: aadd_module.story_id or override_story_id.
  if (listener) {
    auto proposal_listener = listener.Bind();
    proposal_listener->OnProposalAccepted(proposal_id, story_id);
  }
}

void SuggestionEngineImpl::PerformUpdateModuleAction(
    fuchsia::modular::Action* const action, const std::string& story_id) {
  if (!story_provider_) {
    FXL_LOG(WARNING) << "Unable to set entity; no story provider";
    return;
  }

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider_->GetController(story_id, story_controller.NewRequest());
  story_controller->GetModules(fxl::MakeCopyable(
      [this, story_controller = std::move(story_controller),
       module_name = std::move(action->update_module().module_name),
       parameters = std::move(action->update_module().parameters)](
          fidl::VectorPtr<fuchsia::modular::ModuleData> module_datas) {
        for (const auto& module_data : *module_datas) {
          if (module_data.module_path != module_name) {
            continue;
          }
          for (auto& parameter : *parameters) {
            for (auto& entry : *module_data.parameter_map.entries) {
              if (entry.name != parameter.name) {
                continue;
              }

              fuchsia::modular::LinkPtr link;
              story_controller->GetLink(fidl::Clone(entry.link_path),
                                        link.NewRequest());
              switch (parameter.data.Which()) {
                case fuchsia::modular::IntentParameterData::Tag::
                    kEntityReference: {
                  link->SetEntity(parameter.data.entity_reference());
                  break;
                }
                case fuchsia::modular::IntentParameterData::Tag::kJson: {
                  fuchsia::mem::Buffer data;
                  parameter.data.json().Clone(&data);
                  link->Set(nullptr, std::move(data));
                  break;
                }
                case fuchsia::modular::IntentParameterData::Tag::kEntityType:
                case fuchsia::modular::IntentParameterData::Tag::kLinkName:
                case fuchsia::modular::IntentParameterData::Tag::kLinkPath:
                case fuchsia::modular::IntentParameterData::Tag::Invalid: {
                  FXL_LOG(WARNING) << "fuchsia::modular::UpdateModule action "
                                      "with unsupported "
                                   << "parameter data tag #"
                                   << (uint32_t)parameter.data.Which();
                  break;
                }
              }
            }
          }
        }
      }));
}

void SuggestionEngineImpl::PerformCustomAction(
    fuchsia::modular::Action* action) {
  action->custom_action().Bind()->Execute();
}

void SuggestionEngineImpl::PerformSetLinkValueAction(
    const fuchsia::modular::Action& action, const std::string& story_id) {
  if (!story_provider_) {
    FXL_LOG(WARNING) << "Unable to set entity; no story provider";
    return;
  }

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider_->GetController(story_id, story_controller.NewRequest());

  const auto& set_link_value = action.set_link_value_action();
  fuchsia::modular::LinkPtr link;

  story_controller->GetLink(fidl::Clone(set_link_value.link_path),
                            link.NewRequest());
  fsl::SizedVmo vmo;
  FXL_CHECK(fsl::VmoFromString(*set_link_value.value, &vmo));
  link->Set(nullptr, std::move(vmo).ToTransport());
}

void SuggestionEngineImpl::PerformQueryAction(
    const fuchsia::modular::Action& action) {
  // TODO(miguelfrde): instead of keeping a AutoSelectFirstQueryListener as an
  // attribute. Create and move here through an internal structure.
  const auto& query_action = action.query_action();
  Query(auto_select_first_query_listener_binding_.NewBinding(),
        query_action.input, kQueryActionMaxResults);
}

void SuggestionEngineImpl::OnContextUpdate(
    fuchsia::modular::ContextUpdate update) {
  for (auto& entry : update.values.take()) {
    for (const auto& rf_it : ranking_features) {
      if (entry.key == rf_it.first) {  // Update key == rf key
        rf_it.second->UpdateContext(entry.value);
      }
    }
  }
  next_processor_.UpdateRanking();
}

std::string SuggestionEngineImpl::StoryIdFromName(
    const std::string& source_url, const std::string& story_name) {
  auto it = story_name_mapping_.find(StoryNameKey(source_url, story_name));
  if (it != story_name_mapping_.end()) {
    return it->second;
  }
  return "";
}

bool SuggestionEngineImpl::CanComponentUseRichSuggestions(
    const std::string& component_url) {
  // Only kronk is allowed to preload stories in suggestions to make
  // rich suggestions.
  // Proposinator is used for testing.
  return component_url.find("kronk") != std::string::npos ||
         component_url.find("Proposinator") != std::string::npos;
}

}  // namespace modular
