// Copyright 2016 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 <dirent.h>
#include <fcntl.h>
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/fdio/unsafe.h>
#include <lib/fdio/watcher.h>
#include <lib/zx/channel.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <zircon/device/vfs.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

namespace fio = ::llcpp::fuchsia::io;

typedef struct fdio_watcher {
  zx_handle_t h;
  watchdir_func_t func;
  void* cookie;
  int fd;
} fdio_watcher_t;

static zx_status_t fdio_watcher_create(int dirfd, fdio_watcher_t** out) {
  zx::channel client, server;
  zx_status_t status = zx::channel::create(0, &client, &server);
  if (status != ZX_OK) {
    return status;
  }

  fdio_t* io = fdio_unsafe_fd_to_io(dirfd);
  if (io == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }

  zx_handle_t dir_channel = fdio_unsafe_borrow_channel(io);
  if (dir_channel == ZX_HANDLE_INVALID) {
    fdio_unsafe_release(io);
    return ZX_ERR_NOT_SUPPORTED;
  }

  auto result = fio::Directory::Call::Watch(zx::unowned_channel(dir_channel), fio::WATCH_MASK_ALL,
                                            0, std::move(server));
  fdio_unsafe_release(io);
  status = result.status();
  if (status != ZX_OK) {
    return status;
  }
  fio::Directory::WatchResponse* response = result.Unwrap();
  status = response->s;
  if (status != ZX_OK) {
    return status;
  }

  auto watcher = static_cast<fdio_watcher_t*>(malloc(sizeof(fdio_watcher_t)));
  watcher->h = client.release();
  *out = watcher;
  return ZX_OK;
}

// watcher process expects the msg buffer to be len + 1 in length
// as it drops temporary nuls in it while dispatching
static zx_status_t fdio_watcher_process(fdio_watcher_t* w, uint8_t* msg, size_t len) {
  // Message Format: { OP, LEN, DATA[LEN] }
  while (len >= 2) {
    unsigned event = *msg++;
    unsigned namelen = *msg++;

    if (len < (namelen + 2u)) {
      break;
    }

    switch (event) {
      case fio::WATCH_EVENT_ADDED:
      case fio::WATCH_EVENT_EXISTING:
        event = WATCH_EVENT_ADD_FILE;
        break;
      case fio::WATCH_EVENT_REMOVED:
        event = WATCH_EVENT_REMOVE_FILE;
        break;
      case fio::WATCH_EVENT_IDLE:
        event = WATCH_EVENT_WAITING;
        break;
      default:
        // unsupported event
        continue;
    }

    uint8_t tmp = msg[namelen];
    msg[namelen] = 0;

    zx_status_t status;
    if ((status = w->func(w->fd, event, (char*)msg, w->cookie)) != ZX_OK) {
      return status;
    }
    msg[namelen] = tmp;
    len -= (namelen + 2);
    msg += namelen;
  }

  return ZX_OK;
}

static zx_status_t fdio_watcher_loop(fdio_watcher_t* w, zx_time_t deadline) {
  for (;;) {
    // extra byte for watcher process use
    uint8_t msg[fio::MAX_BUF + 1];
    uint32_t sz = fio::MAX_BUF;
    zx_status_t status;
    if ((status = zx_channel_read(w->h, 0, msg, nullptr, sz, 0, &sz, nullptr)) < 0) {
      if (status != ZX_ERR_SHOULD_WAIT) {
        return status;
      }
      if ((status = zx_object_wait_one(w->h, ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, deadline,
                                       nullptr)) < 0) {
        return status;
      }
      continue;
    }

    if ((status = fdio_watcher_process(w, msg, sz)) != ZX_OK) {
      return status;
    }
  }
}

static void fdio_watcher_destroy(fdio_watcher_t* watcher) {
  zx_handle_close(watcher->h);
  free(watcher);
}

__EXPORT
zx_status_t fdio_watch_directory(int dirfd, watchdir_func_t cb, zx_time_t deadline, void* cookie) {
  fdio_watcher_t* watcher = nullptr;

  zx_status_t status;
  if ((status = fdio_watcher_create(dirfd, &watcher)) < 0) {
    return status;
  }

  watcher->func = cb;
  watcher->cookie = cookie;
  watcher->fd = dirfd;
  status = fdio_watcher_loop(watcher, deadline);

  fdio_watcher_destroy(watcher);
  return status;
}
