// 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 "peridot/lib/fidl/app_client.h"

#include <fcntl.h>

#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fdio/limits.h>
#include <lib/fdio/util.h>
#include <lib/fsl/io/fd.h>
#include <lib/fxl/files/directory.h>
#include <lib/fxl/files/unique_fd.h>
#include <zircon/processargs.h>

namespace modular {
AppClientBase::AppClientBase(fuchsia::sys::Launcher* const launcher,
                             fuchsia::modular::AppConfig config,
                             std::string data_origin,
                             fuchsia::sys::ServiceListPtr additional_services)
    : AsyncHolderBase(config.url) {
  fuchsia::sys::LaunchInfo launch_info;
  launch_info.directory_request = services_.NewRequest();
  launch_info.url = config.url;
  std::vector<std::string> args;
  for (const auto& arg : *config.args) {
    launch_info.arguments.push_back(arg);
  }

  if (!data_origin.empty()) {
    if (!files::CreateDirectory(data_origin)) {
      FXL_LOG(ERROR) << "Unable to create directory at " << data_origin;
      return;
    }
    launch_info.flat_namespace = fuchsia::sys::FlatNamespace::New();
    launch_info.flat_namespace->paths.push_back("/data");

    fxl::UniqueFD dir(open(data_origin.c_str(), O_DIRECTORY | O_RDONLY));
    if (!dir.is_valid()) {
      FXL_LOG(ERROR) << "Unable to open directory at " << data_origin
                     << ". errno: " << errno;
      return;
    }

    launch_info.flat_namespace->directories.push_back(
        fsl::CloneChannelFromFileDescriptor(dir.get()));
    if (!launch_info.flat_namespace->directories.at(0)) {
      FXL_LOG(ERROR) << "Unable create a handle from  " << data_origin;
      return;
    }
  }

  if (additional_services) {
    launch_info.additional_services = std::move(additional_services);
  }
  launcher->CreateComponent(std::move(launch_info), app_.NewRequest());
}

AppClientBase::~AppClientBase() = default;

void AppClientBase::ImplTeardown(std::function<void()> done) {
  ServiceTerminate(std::move(done));
}

void AppClientBase::ImplReset() {
  app_.Unbind();
  ServiceUnbind();
}

void AppClientBase::SetAppErrorHandler(
    const std::function<void()>& error_handler) {
  app_.set_error_handler(
      [error_handler](zx_status_t status) { error_handler(); });
}

void AppClientBase::ServiceTerminate(const std::function<void()>& /* done */) {}

void AppClientBase::ServiceUnbind() {}

template <>
void AppClient<fuchsia::modular::Lifecycle>::ServiceTerminate(
    const std::function<void()>& done) {
  SetAppErrorHandler(done);
  if (primary_service())
    primary_service()->Terminate();
}

}  // namespace modular
