// Copyright 2013 The Flutter 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 FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_RUNNER_DART_TEST_COMPONENT_CONTROLLER_V2_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_RUNNER_DART_TEST_COMPONENT_CONTROLLER_V2_H_

#include <memory>

#include <fuchsia/component/runner/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <fuchsia/test/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/executor.h>
#include <lib/async/cpp/wait.h>
#include <lib/fdio/namespace.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/zx/timer.h>

#include <lib/fidl/cpp/binding_set.h>
#include "lib/fidl/cpp/binding.h"
#include "runtime/dart/utils/mapped_resource.h"
#include "third_party/dart/runtime/include/dart_api.h"

namespace dart_runner {

/// Starts a Dart test component written in CFv2. It's different from
/// DartComponentControllerV2 in that it must implement the
/// |fuchsia.test.Suite| protocol. It was forked to avoid a naming clash
/// between the two classes' methods as the Suite protocol requires a Run()
/// method for the test_manager to call on. This way, we avoid an extra layer
/// between the test_manager and actual test execution.
/// TODO(fxb/98369): Look into combining the two component classes once dart
/// testing is stable.
class DartTestComponentControllerV2
    : public fuchsia::component::runner::ComponentController,
      public fuchsia::test::Suite {
  using DoneCallback = fit::function<void(DartTestComponentControllerV2*)>;

 public:
  DartTestComponentControllerV2(
      fuchsia::component::runner::ComponentStartInfo start_info,
      std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
      fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
          controller,
      DoneCallback done_callback);

  ~DartTestComponentControllerV2() override;

  /// Sets up the controller.
  ///
  /// This should be called before |Run|.
  void SetUp();

  /// |Suite| protocol implementation.
  void GetTests(
      fidl::InterfaceRequest<fuchsia::test::CaseIterator> iterator) override;

  /// |Suite| protocol implementation.
  void Run(std::vector<fuchsia::test::Invocation> tests,
           fuchsia::test::RunOptions options,
           fidl::InterfaceHandle<fuchsia::test::RunListener> listener) override;

  fidl::InterfaceRequestHandler<fuchsia::test::Suite> GetHandler() {
    return suite_bindings_.GetHandler(this, loop_->dispatcher());
  }

 private:
  /// Helper for actually running the Dart main. Returns Returns a promise.
  fpromise::promise<> RunDartMain();

  /// Creates and binds the namespace for this component. Returns true if
  /// successful, false otherwise.
  bool CreateAndBindNamespace();

  bool SetUpFromKernel();
  bool SetUpFromAppSnapshot();

  bool CreateIsolate(const uint8_t* isolate_snapshot_data,
                     const uint8_t* isolate_snapshot_instructions);

  // |ComponentController|
  void Kill() override;
  void Stop() override;

  // Idle notification.
  void MessageEpilogue(Dart_Handle result);
  void OnIdleTimer(async_dispatcher_t* dispatcher,
                   async::WaitBase* wait,
                   zx_status_t status,
                   const zx_packet_signal* signal);

  // |CaseIterator|
  class CaseIterator final : public fuchsia::test::CaseIterator {
   public:
    CaseIterator(fidl::InterfaceRequest<fuchsia::test::CaseIterator> request,
                 async_dispatcher_t* dispatcher,
                 std::string test_component_name,
                 fit::function<void(CaseIterator*)> done_callback);

    void GetNext(GetNextCallback callback) override;

   private:
    bool first_case_ = true;
    fidl::Binding<fuchsia::test::CaseIterator> binding_;
    std::string test_component_name_;
    fit::function<void(CaseIterator*)> done_callback_;
  };

  std::unique_ptr<CaseIterator> RemoveCaseInterator(CaseIterator*);

  // We only need one case_listener currently as dart tests are run as one
  // large test file. In future iterations, case_listeners must be
  // created per test case.
  fidl::InterfacePtr<fuchsia::test::CaseListener> case_listener_;
  std::map<CaseIterator*, std::unique_ptr<CaseIterator>> case_iterators_;

  // |Suite|

  /// Exposes suite protocol on behalf of test component.
  std::string test_component_name_;
  std::unique_ptr<sys::ComponentContext> suite_context_;
  fidl::BindingSet<fuchsia::test::Suite> suite_bindings_;

  // The loop must be the first declared member so that it gets destroyed after
  // binding_ which expects the existence of a loop.
  std::unique_ptr<async::Loop> loop_;
  async::Executor executor_;

  std::string label_;
  std::string url_;
  std::shared_ptr<sys::ServiceDirectory> runner_incoming_services_;
  std::string data_path_;
  std::unique_ptr<sys::ComponentContext> context_;

  fuchsia::component::runner::ComponentStartInfo start_info_;
  fidl::Binding<fuchsia::component::runner::ComponentController> binding_;
  DoneCallback done_callback_;

  zx::socket out_, err_, out_client_, err_client_;
  fdio_ns_t* namespace_ = nullptr;
  int stdout_fd_ = -1;
  int stderr_fd_ = -1;

  dart_utils::ElfSnapshot elf_snapshot_;                      // AOT snapshot
  dart_utils::MappedResource isolate_snapshot_data_;          // JIT snapshot
  dart_utils::MappedResource isolate_snapshot_instructions_;  // JIT snapshot
  std::vector<dart_utils::MappedResource> kernel_peices_;

  Dart_Isolate isolate_;
  int32_t return_code_ = 0;

  zx::time idle_start_{0};
  zx::timer idle_timer_;
  async::WaitMethod<DartTestComponentControllerV2,
                    &DartTestComponentControllerV2::OnIdleTimer>
      idle_wait_{this};

  // Disallow copy and assignment.
  DartTestComponentControllerV2(const DartTestComponentControllerV2&) = delete;
  DartTestComponentControllerV2& operator=(
      const DartTestComponentControllerV2&) = delete;
};

}  // namespace dart_runner

#endif  // FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_RUNNER_DART_TEST_COMPONENT_CONTROLLER_V2_H_
