// 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 <memory>
#include <sstream>
#include <string>

#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/ui/viewsv1token/cpp/fidl.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/context/cpp/context_helper.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fostr/fidl/fuchsia/modular/formatting.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/macros.h>

#include "peridot/lib/fidl/array_to_string.h"
#include "peridot/lib/rapidjson/rapidjson.h"
#include "peridot/lib/testing/component_main.h"
#include "peridot/lib/testing/session_shell_base.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/link_context_entities/defs.h"

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

namespace {

const char kStoryName[] = "story";

// A context reader watcher implementation.
class ContextListenerImpl : fuchsia::modular::ContextListener {
 public:
  ContextListenerImpl() : binding_(this) {
    handler_ = [](const fuchsia::modular::ContextValue&) {};
  }

  ~ContextListenerImpl() override = default;

  // Registers itself a watcher on the given story provider. Only one story
  // provider can be watched at a time.
  void Listen(fuchsia::modular::ContextReader* const context_reader) {
    // Subscribe to all entity values.
    fuchsia::modular::ContextSelector selector;
    selector.type = fuchsia::modular::ContextValueType::ENTITY;

    fuchsia::modular::ContextQuery query;
    modular::AddToContextQuery(&query, "all", std::move(selector));

    context_reader->Subscribe(std::move(query), binding_.NewBinding());
    binding_.set_error_handler([](zx_status_t status) {
      FXL_LOG(ERROR) << "Lost fuchsia::modular::ContextListener connection to "
                        "fuchsia::modular::ContextReader.";
    });
  }

  using Handler = std::function<void(const fuchsia::modular::ContextValue&)>;

  void Handle(const Handler& handler) { handler_ = handler; }

  // Deregisters itself from the watched story provider.
  void Reset() { binding_.Unbind(); }

 private:
  // |fuchsia::modular::ContextListener|
  void OnContextUpdate(fuchsia::modular::ContextUpdate update) override {
    FXL_LOG(INFO) << "ContextListenerImpl::OnUpdate()";
    if (auto values = modular::TakeContextValue(&update, "all")) {
      for (const auto& value : *values) {
        FXL_LOG(INFO) << "ContextListenerImpl::OnUpdate() " << value;
        handler_(value);
      }
    };
  }

  fidl::Binding<fuchsia::modular::ContextListener> binding_;
  Handler handler_;

  FXL_DISALLOW_COPY_AND_ASSIGN(ContextListenerImpl);
};

// Cf. README.md for what this test does and how.
class TestApp : public modular::testing::SessionShellBase {
 public:
  TestApp(component::StartupContext* const startup_context)
      : SessionShellBase(startup_context) {
    TestInit(__FILE__);

    startup_context->ConnectToEnvironmentService(puppet_master_.NewRequest());

    fuchsia::modular::IntelligenceServicesPtr intelligence_services;
    startup_context->ConnectToEnvironmentService(
        intelligence_services.NewRequest());
    intelligence_services->GetContextReader(context_reader_.NewRequest());
    context_listener_.Listen(context_reader_.get());
    context_reader_.set_error_handler([](zx_status_t status) {
      FXL_LOG(ERROR) << "Lost fuchsia::modular::ContextReader connection.";
    });

    CreateStory();
  }

  ~TestApp() override = default;

 private:
  TestPoint create_story_{"CreateStory()"};

  void CreateStory() {
    puppet_master_->ControlStory(kStoryName, story_puppet_master_.NewRequest());

    std::vector<fuchsia::modular::StoryCommand> commands;
    fuchsia::modular::AddMod add_mod;
    add_mod.mod_name.push_back("root");
    add_mod.intent.handler = kModuleUrl;
    add_mod.intent.action = kModuleAction;

    fuchsia::modular::StoryCommand command;
    command.set_add_mod(std::move(add_mod));
    commands.push_back(std::move(command));

    story_puppet_master_->Enqueue(std::move(commands));
    story_puppet_master_->Execute(
        [this](fuchsia::modular::ExecuteResult result) {
          create_story_.Pass();
          StartStory();
        });
  }

  TestPoint start_story_enter_{"StartStory() Enter"};
  TestPoint start_story_exit_{"StartStory() Exit"};

  void StartStory() {
    start_story_enter_.Pass();

    context_listener_.Handle(
        [this](const fuchsia::modular::ContextValue& value) {
          ProcessContextValue(value);
        });

    story_provider()->GetController(kStoryName, story_controller_.NewRequest());
    story_controller_->RequestStart();

    start_story_exit_.Pass();
  }

  TestPoint get_context_topic_1_{"GetContextTopic() value=1"};
  int get_context_topic_1_called_{};
  TestPoint get_context_topic_2_{"GetContextTopic() value=2"};
  int get_context_topic_2_called_{};

  void ProcessContextValue(const fuchsia::modular::ContextValue& value) {
    // The context value has metadata that is derived from the story id in
    // which it was published.
    if (!value.meta.story || !value.meta.link || !value.meta.entity) {
      FXL_LOG(ERROR) << "fuchsia::modular::ContextValue missing metadata: "
                     << value;
      return;
    }

    if (value.meta.story->id != kStoryName ||
        value.meta.entity->type.is_null() ||
        value.meta.entity->type->size() != 1) {
      FXL_LOG(ERROR) << "fuchsia::modular::ContextValue metadata is incorrect: "
                     << value;
      return;
    }

    modular::JsonDoc doc;
    doc.Parse(value.content);

    if (doc.HasParseError()) {
      FXL_LOG(ERROR) << "JSON Parse Error" << value.content;
      Logout();
      return;
    }

    if (!doc.IsObject()) {
      FXL_LOG(ERROR) << "JSON not an Object" << value.content;
      Logout();
      return;
    }

    if (!doc.HasMember("value")) {
      FXL_LOG(ERROR) << "JSON missing 'value': " << value.content;
      Logout();
      return;
    }

    const std::string value_property{doc["value"].GetString()};
    const std::string type{value.meta.entity->type->at(0)};
    if (value_property != "value1" && value_property != "value2") {
      FXL_LOG(ERROR) << "JSON 'value' property (set by module) wrong: "
                     << value_property;
      Logout();
      return;
    }

    if (value_property == "value1" && type == "type1" &&
        value.meta.link->name == "link1") {
      if (++get_context_topic_1_called_ == 1) {
        get_context_topic_1_.Pass();
      }
    } else if (value_property == "value2" && type == "type2" &&
               value.meta.link->name == "link2") {
      if (++get_context_topic_2_called_ == 1) {
        get_context_topic_2_.Pass();
      }
    }

    if (get_context_topic_1_called_ > 0 && get_context_topic_2_called_ > 0) {
      context_listener_.Reset();
      context_listener_.Handle(
          [this](const fuchsia::modular::ContextValue&) {});
      Logout();
    }
  }

  void Logout() {
    Signal(modular::testing::kTestShutdown);
  }

  fuchsia::modular::PuppetMasterPtr puppet_master_;
  fuchsia::modular::StoryPuppetMasterPtr story_puppet_master_;

  fuchsia::modular::StoryControllerPtr story_controller_;

  fuchsia::modular::ContextReaderPtr context_reader_;
  ContextListenerImpl context_listener_;

  FXL_DISALLOW_COPY_AND_ASSIGN(TestApp);
};

}  // namespace

int main(int /*argc*/, const char** /*argv*/) {
  modular::testing::ComponentMain<TestApp>();
  return 0;
}
