// Copyright 2019 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.

#ifndef SRC_MEDIA_CODEC_CODECS_VAAPI_CODEC_RUNNER_APP_H_
#define SRC_MEDIA_CODEC_CODECS_VAAPI_CODEC_RUNNER_APP_H_

#include <fuchsia/mediacodec/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/inspect/cpp/inspector.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/log_level.h>
#include <lib/syslog/cpp/log_settings.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace-provider/provider.h>

#include <initializer_list>
#include <memory>
#include <string>

#include "local_single_codec_factory.h"

// If a software can only provide an encoder or decoder, the other should be
// assigned NoAdapter in the template arguments, e.g.:
//   CodecRunnerApp<CodecAdapterFfmpeg, NoAdapter>
template <typename Decoder, typename Encoder>
class CodecRunnerApp {
 public:
  CodecRunnerApp()
      : codec_admission_control_(std::make_unique<CodecAdmissionControl>(loop_.dispatcher())) {}

  void Init() {
    static const std::initializer_list<std::string> kLogTags = {"vaapi_codec_runner"};
#ifdef NDEBUG
    fuchsia_logging::SetTags(kLogTags);
#else
    fuchsia_logging::SetLogSettings({.min_log_level = fuchsia_logging::LOG_DEBUG}, kLogTags);
#endif

    trace_provider_ =
        std::make_unique<trace::TraceProviderWithFdio>(loop_.dispatcher(), "vaapi_codec_runner");

    // This is bit of a misnomer since CodecRunnerApp isn't a driver but instead a component. Since
    // we need a new instance for every FIDL connection a driver does not make sense currently.
    codec_diagnostics_ =
        std::make_unique<CodecDiagnostics>("vaapi_codec_runner", loop_.dispatcher());

    component_context_->outgoing()->AddPublicService(
        fidl::InterfaceRequestHandler<fuchsia::mediacodec::CodecFactory>(
            [this, codec_admission_control = codec_admission_control_.get()](
                fidl::InterfaceRequest<fuchsia::mediacodec::CodecFactory> request) {
              // We RemoveService() near the end of the present lambda, so it
              // should be impossible to receive a second CodecFactory request.
              FX_DCHECK(!codec_factory_);

              fidl::InterfaceHandle<fuchsia::sysmem::Allocator> sysmem;
              component_context_->svc()->Connect(sysmem.NewRequest());
              codec_factory_ = std::make_unique<LocalSingleCodecFactory<Decoder, Encoder>>(
                  loop_.dispatcher(), std::move(sysmem), std::move(request),
                  [this](std::unique_ptr<CodecImpl> created_codec_instance) {
                    ZX_DEBUG_ASSERT(!codec_instance_);
                    if (!created_codec_instance) {
                      // Drop factory and close factory channel on factory
                      // failure to create instance.
                      codec_factory_ = nullptr;
                      // The codec_instance_ channel is the only reason for the
                      // isolate to exist.
                      loop_.Quit();
                      return;
                    }
                    // Own codec implementation and bind it.
                    codec_instance_ = std::move(created_codec_instance);
                    codec_instance_->BindAsync([this] {
                      // Drop codec implementation and close channel on
                      // error.
                      codec_instance_ = nullptr;
                      // The codec_instance_ channel is the only reason for
                      // the isolate to exist.
                      loop_.Quit();
                    });
                    // Drop factory and close factory channel.
                    codec_factory_ = nullptr;
                  },
                  codec_admission_control,
                  [this](zx_status_t error) {
                    // Drop factory and close factory channel on error.
                    codec_factory_ = nullptr;
                    // The codec_instance_ channel is the only reason for
                    // the isolate to exist.  If codec_instance_ wasn't
                    // created via the codec_factory_ before this point,
                    // it'll never be created via codec_factory_.
                    if (!codec_instance_) {
                      loop_.Quit();
                    }
                  },
                  codec_diagnostics_.get());
              // This runner only expects a single Local Codec Factory to ever
              // be requested.
              //
              // This call deletes the presently-running lambda, so nothing
              // after this call can use the lambda's captures, including the
              // "this" pointer implicitly.
              component_context_->outgoing()
                  ->RemovePublicService<fuchsia::mediacodec::CodecFactory>();
            }));
  }

  void Serve() { component_context_->outgoing()->ServeFromStartupInfo(); }

  void Run() {
    loop_.Run();

    // Run the loop_.Shutdown() here (before ~CodecRunnerApp), so that any
    // pending tasks get deleted sooner rather than later.  The only pending
    // task we expect to potentially be deleted here is the task queued in
    // ~CodecImpl that does ~CodecAdmission and then ~zx::channel (even if the
    // task is just deleted and not run).  That task needs to run or be
    // deleted before ~CodecAdmissionControl.
    loop_.Shutdown();
  }

  std::unique_ptr<sys::ComponentContext>& component_context() { return component_context_; }

 private:
  async::Loop loop_{&kAsyncLoopConfigAttachToCurrentThread};
  std::unique_ptr<sys::ComponentContext> component_context_{sys::ComponentContext::Create()};
  std::unique_ptr<CodecAdmissionControl> codec_admission_control_;
  std::unique_ptr<LocalSingleCodecFactory<Decoder, Encoder>> codec_factory_;
  std::unique_ptr<CodecImpl> codec_instance_;
  std::unique_ptr<trace::TraceProviderWithFdio> trace_provider_;
  std::unique_ptr<CodecDiagnostics> codec_diagnostics_;
};

#endif  // SRC_MEDIA_CODEC_CODECS_VAAPI_CODEC_RUNNER_APP_H_
