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

#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/directory.h>
#include <lib/fs-pty/service.h>
#include <lib/zx/eventpair.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include "pty-server-vnode.h"
#include "pty-server.h"
#include "src/lib/storage/vfs/cpp/pseudo_dir.h"
#include "src/lib/storage/vfs/cpp/synchronous_vfs.h"
#include "src/lib/storage/vfs/cpp/vfs_types.h"
#include "src/lib/storage/vfs/cpp/vnode.h"
#include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h"

// Each Open() on this Vnode redirects to a new PtyServerVnode
class PtyGeneratingVnode : public fs::Vnode {
 public:
  PtyGeneratingVnode(fs::Vfs* vfs) : vfs_(vfs) {}
  ~PtyGeneratingVnode() override = default;

  zx_status_t GetNodeInfoForProtocol([[maybe_unused]] fs::VnodeProtocol protocol,
                                     [[maybe_unused]] fs::Rights rights,
                                     fs::VnodeRepresentation* info) override {
    // This should only actually be seen by something querying with VNODE_REF_ONLY.
    *info = fs::VnodeRepresentation::Tty{.event = {}};
    return ZX_OK;
  }

  fs::VnodeProtocolSet GetProtocols() const final { return fs::VnodeProtocol::kTty; }

 private:
  zx_status_t OpenNode(ValidatedOptions options, fbl::RefPtr<Vnode>* out_redirect) override {
    fbl::RefPtr<PtyServer> server;
    zx_status_t status = PtyServer::Create(&server, vfs_);
    if (status != ZX_OK) {
      return status;
    }
    *out_redirect = fbl::MakeRefCounted<PtyServerVnode>(std::move(server));
    return ZX_OK;
  }

  fs::Vfs* vfs_;
};

int main(int argc, const char** argv) {
  zx_status_t status;
  if ((status = StdoutToDebuglog::Init()) != ZX_OK) {
    printf("console: failed to init stdout to debuglog: %s\n", zx_status_get_string(status));
    return -1;
  }

  async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
  async_dispatcher_t* dispatcher = loop.dispatcher();
  fs::SynchronousVfs vfs(dispatcher);

  auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
  auto svc_dir = fbl::MakeRefCounted<fs::PseudoDir>();
  if ((status = root_dir->AddEntry("svc", svc_dir)) != ZX_OK) {
    printf("console: failed to add svc to root dir: %s\n", zx_status_get_string(status));
    return -1;
  }
  if ((status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fuchsia_hardware_pty::Device>,
                                  fbl::MakeRefCounted<PtyGeneratingVnode>(&vfs))) != ZX_OK) {
    printf("console: failed to add %s to svc dir: %s\n",
           fidl::DiscoverableProtocolName<fuchsia_hardware_pty::Device>,
           zx_status_get_string(status));
    return -1;
  }

  if ((status = vfs.ServeDirectory(root_dir, fidl::ServerEnd<fuchsia_io::Directory>(zx::channel(
                                                 zx_take_startup_handle(PA_DIRECTORY_REQUEST))))) !=
      ZX_OK) {
    printf("console: failed to serve startup handle: %s\n", zx_status_get_string(status));
    return -1;
  }

  ZX_ASSERT_MSG((status = loop.Run()) == ZX_OK, "%s", zx_status_get_string(status));
  return 0;
}
