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

#include <fuchsia/modular/cpp/fidl.h>
#include <lib/app_driver/cpp/app_driver.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/ui/base_view/cpp/v1_base_view.h>
#include <trace-provider/provider.h>
#include <zx/eventpair.h>

#include "peridot/lib/fidl/single_service_app.h"

namespace {

constexpr uint32_t kChildKey = 1;
constexpr int kSwapSeconds = 5;
constexpr std::array<const char*, 2> kModuleQueries{
    {"swap_module1", "swap_module2"}};

class RecipeView : public scenic::V1BaseView {
 public:
  explicit RecipeView(scenic::ViewContext view_context)
      : V1BaseView(std::move(view_context), "RecipeView") {}

  ~RecipeView() override = default;

  void SetChild(zx::eventpair view_token) {
    if (host_node_) {
      GetViewContainer()->RemoveChild2(kChildKey, zx::eventpair());
      host_node_->Detach();
      host_node_.reset();
    }

    if (view_token) {
      host_node_ = std::make_unique<scenic::EntityNode>(session());

      zx::eventpair host_import_token;
      host_node_->ExportAsRequest(&host_import_token);
      parent_node().AddChild(*host_node_);

      GetViewContainer()->AddChild2(kChildKey, std::move(view_token),
                                    std::move(host_import_token));
    }
  }

 private:
  // |scenic::V1BaseView|
  void OnPropertiesChanged(fuchsia::ui::viewsv1::ViewProperties) override {
    if (host_node_) {
      auto child_properties = fuchsia::ui::viewsv1::ViewProperties::New();
      fidl::Clone(properties(), child_properties.get());
      GetViewContainer()->SetChildProperties(kChildKey,
                                             std::move(child_properties));
    }
  }

  std::unique_ptr<scenic::EntityNode> host_node_;
};

class RecipeApp : public modular::ViewApp {
 public:
  RecipeApp(component::StartupContext* const startup_context)
      : ViewApp(startup_context) {
    startup_context->ConnectToEnvironmentService(module_context_.NewRequest());
    SwapModule();
  }

  ~RecipeApp() override = default;

 private:
  // |ViewApp|
  void CreateView(
      zx::eventpair view_token,
      fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
      fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services)
      override {
    auto scenic =
        startup_context()
            ->ConnectToEnvironmentService<fuchsia::ui::scenic::Scenic>();
    scenic::ViewContext view_context = {
        .session_and_listener_request =
            scenic::CreateScenicSessionPtrAndListenerRequest(scenic.get()),
        .view_token = std::move(view_token),
        .incoming_services = std::move(incoming_services),
        .outgoing_services = std::move(outgoing_services),
        .startup_context = startup_context(),
    };
    view_ = std::make_unique<RecipeView>(std::move(view_context));
    SetChild();
  }

  void SwapModule() {
    StartModule(kModuleQueries[query_index_]);
    query_index_ = (query_index_ + 1) % kModuleQueries.size();
    async::PostDelayedTask(async_get_default_dispatcher(),
                           [this] { SwapModule(); }, zx::sec(kSwapSeconds));
  }

  void StartModule(const std::string& module_query) {
    if (module_) {
      module_->Stop([this, module_query] {
        module_.Unbind();
        module_view_.Unbind();
        StartModule(module_query);
      });
      return;
    }

    // This module is named after its URL.
    fuchsia::modular::Intent intent;
    intent.handler = module_query;
    module_context_->EmbedModule(
        module_query, std::move(intent), module_.NewRequest(),
        module_view_.NewRequest(),
        [](const fuchsia::modular::StartModuleStatus&) {});
    SetChild();
  }

  void SetChild() {
    if (view_ && module_view_) {
      view_->SetChild(
          zx::eventpair(module_view_.Unbind().TakeChannel().release()));
    }
  }

  fuchsia::modular::ModuleContextPtr module_context_;
  fuchsia::modular::ModuleControllerPtr module_;
  fuchsia::ui::viewsv1token::ViewOwnerPtr module_view_;
  std::unique_ptr<RecipeView> view_;

  int query_index_ = 0;
};

}  // namespace

int main(int /*argc*/, const char** /*argv*/) {
  async::Loop loop(&kAsyncLoopConfigAttachToThread);
  trace::TraceProvider trace_provider(loop.dispatcher());

  auto context = component::StartupContext::CreateFromStartupInfo();
  modular::AppDriver<RecipeApp> driver(
      context->outgoing().deprecated_services(),
      std::make_unique<RecipeApp>(context.get()), [&loop] { loop.Quit(); });

  loop.Run();
  return 0;
}
