// 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 "runner.h"

#include <zircon/status.h>
#include <zircon/types.h>

#include <sstream>
#include <utility>

#include "flutter/fml/make_copyable.h"
#include "flutter/lib/ui/text/font_collection.h"
#include "fuchsia_font_manager.h"
#include "lib/icu_data/cpp/icu_data.h"
#include "third_party/flutter/runtime/dart_vm.h"
#include "third_party/skia/include/core/SkGraphics.h"
#include "topaz/runtime/dart/utils/vmservice_object.h"

namespace flutter {

static void SetProcessName() {
  std::stringstream stream;
  stream << "io.flutter.runner.";
  if (blink::DartVM::IsRunningPrecompiledCode()) {
    stream << "aot";
  } else {
    stream << "jit";
  }
  const auto name = stream.str();
  zx::process::self()->set_property(ZX_PROP_NAME, name.c_str(), name.size());
}

static void SetThreadName(const std::string& thread_name) {
  zx::thread::self()->set_property(ZX_PROP_NAME, thread_name.c_str(),
                                   thread_name.size());
}

Runner::Runner()
    : host_context_(component::StartupContext::CreateFromStartupInfo()) {
#if !defined(DART_PRODUCT)
  // The VM service isolate uses the process-wide namespace. It writes the
  // vm service protocol port under /tmp. The VMServiceObject exposes that
  // port number to The Hub.
  vmservice_object_ = fuchsia::dart::VMServiceObject::Create(
      host_context_->outgoing().object_dir());
#endif  // !defined(DART_PRODUCT)

  SkGraphics::Init();

  SetupICU();

  SetProcessName();

  SetThreadName("io.flutter.runner.main");

  host_context_->outgoing().deprecated_services()->AddService<fuchsia::sys::Runner>(
      std::bind(&Runner::RegisterApplication, this, std::placeholders::_1));
}

Runner::~Runner() {
  host_context_->outgoing().deprecated_services()->RemoveService<fuchsia::sys::Runner>();
}

void Runner::RegisterApplication(
    fidl::InterfaceRequest<fuchsia::sys::Runner> request) {
  active_applications_bindings_.AddBinding(this, std::move(request));
}

void Runner::StartComponent(
    fuchsia::sys::Package package, fuchsia::sys::StartupInfo startup_info,
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
  TRACE_DURATION("flutter", "StartComponent", "url", package.resolved_url);
  // Notes on application termination: Application typically terminate on the
  // thread on which they were created. This usually means the thread was
  // specifically created to host the application. But we want to ensure that
  // access to the active applications collection is made on the same thread. So
  // we capture the runner in the termination callback. There is no risk of
  // there being multiple application runner instance in the process at the same
  // time. So it is safe to use the raw pointer.
  Application::TerminationCallback termination_callback =
      [task_runner =
           deprecated_loop::MessageLoop::GetCurrent()->task_runner(),  //
       application_runner = this                                       //
  ](const Application* application) {
        task_runner->PostTask([application_runner, application]() {
          application_runner->OnApplicationTerminate(application);
        });
      };

  auto thread_application_pair = Application::Create(
      std::move(termination_callback),  // termination callback
      std::move(package),               // application pacakge
      std::move(startup_info),          // startup info
      std::move(controller)             // controller request
  );

  auto key = thread_application_pair.second.get();

  active_applications_[key] = std::move(thread_application_pair);
}

void Runner::OnApplicationTerminate(const Application* application) {
  auto app = active_applications_.find(application);
  if (app == active_applications_.end()) {
    FML_LOG(INFO)
        << "The remote end of the application runner tried to terminate an "
           "application that has already been terminated, possibly because we "
           "initiated the termination";
    return;
  }
  auto& active_application = app->second;

  // Grab the items out of the entry because we will have to rethread the
  // destruction.
  auto application_to_destroy = std::move(active_application.application);
  auto application_destruction_thread = std::move(active_application.thread);

  // Delegate the entry.
  active_applications_.erase(application);

  // Post the task to destroy the application and quit its message loop.
  auto runner = application_destruction_thread->TaskRunner();
  runner->PostTask(fml::MakeCopyable(
      [instance = std::move(application_to_destroy)]() mutable {
        instance.reset();

        deprecated_loop::MessageLoop::GetCurrent()->PostQuitTask();
      }));

  // This works because just posted the quit task on the hosted thread.
  application_destruction_thread->Join();
}

void Runner::SetupICU() {
  if (!icu_data::Initialize(host_context_.get())) {
    FML_LOG(ERROR) << "Could not initialize ICU data.";
  }
}

}  // namespace flutter
