// Copyright 2017 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 <fuchsia/modular/cpp/fidl.h>
#include <lib/app_driver/cpp/module_driver.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/callback/scoped_callback.h>
#include <lib/component/cpp/connect.h>

#include "peridot/public/lib/integration_testing/cpp/reporting.h"
#include "peridot/public/lib/integration_testing/cpp/testing.h"
#include "peridot/tests/common/defs.h"
#include "peridot/tests/suggestion/defs.h"

using modular::testing::Await;
using modular::testing::Signal;
using modular::testing::TestPoint;

namespace {

// Cf. README.md for what this test does and how.
class TestModule : fuchsia::modular::ProposalListener {
 public:
  TestPoint initialized_{"Root module initialized"};
  TestPoint received_story_id_{"Root module received story id"};
  TestPoint proposal_was_accepted_{"fuchsia::modular::Proposal was accepted"};

  TestModule(modular::ModuleHost* module_host,
             fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider>
                 view_provider_request)
      : module_host_(module_host),
        view_provider_(std::move(view_provider_request)) {
    modular::testing::Init(module_host_->startup_context(), __FILE__);
    initialized_.Pass();

    fuchsia::modular::IntelligenceServicesPtr intelligence_services;

    module_host_->startup_context()->ConnectToEnvironmentService(
        intelligence_services.NewRequest());
    intelligence_services->GetProposalPublisher(
        proposal_publisher_.NewRequest());

    module_host_->module_context()->GetStoryId(
        [this](const fidl::StringPtr& story_id) {
          received_story_id_.Pass();

          fuchsia::modular::SetFocusState focus_story;
          focus_story.focused = true;

          fuchsia::modular::StoryCommand command;
          command.set_set_focus_state(std::move(focus_story));

          // Craft a minimal suggestion proposal.
          fuchsia::modular::SuggestionDisplay suggestion_display;
          suggestion_display.headline = "foo";
          suggestion_display.subheadline = "bar";
          suggestion_display.details = "baz";
          suggestion_display.color = 0xffff0000;

          fuchsia::modular::Proposal proposal;
          proposal.id = kProposalId;
          proposal.affinity.resize(0);
          proposal.story_name = story_id;
          proposal.display = std::move(suggestion_display);
          proposal.on_selected.push_back(std::move(command));
          proposal_listener_bindings_.AddBinding(
              this, proposal.listener.NewRequest());

          proposal_publisher_->Propose(std::move(proposal));

          Await("suggestion_proposal_received", [this] {
            Await("proposal_was_accepted", [this] {
              proposal_was_accepted_.Pass();
              Signal(kSuggestionTestModuleDone);
            });
          });
        });
  }

  // Called by ModuleDriver.
  TestPoint stopped_{"Root module stopped"};
  void Terminate(fit::function<void()> done) {
    stopped_.Pass();
    modular::testing::Done(std::move(done));
  }

  // |fuchsia::modular::ProposalListener|
  void OnProposalAccepted(std::string proposal_id,
                          fidl::StringPtr story_id) override {
    Signal("proposal_was_accepted");
  }

 private:
  modular::ModuleHost* const module_host_;
  fuchsia::modular::ModuleContextPtr module_context_;
  fuchsia::modular::ProposalPublisherPtr proposal_publisher_;
  fidl::BindingSet<fuchsia::modular::ProposalListener>
      proposal_listener_bindings_;

  // We keep the view provider around so that story shell can hold a view for
  // us, but don't do anything with it.
  fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider> view_provider_;
  FXL_DISALLOW_COPY_AND_ASSIGN(TestModule);
};

}  // namespace

int main(int /*argc*/, const char** /*argv*/) {
  async::Loop loop(&kAsyncLoopConfigAttachToThread);
  auto context = component::StartupContext::CreateFromStartupInfo();
  modular::ModuleDriver<TestModule> driver(context.get(),
                                           [&loop] { loop.Quit(); });
  loop.Run();
  return 0;
}
