// 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 "console.h"

#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/fdio/vfs.h>
#include <lib/zx/channel.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <algorithm>
#include <iterator>
#include <thread>

#include <fbl/string_buffer.h>

Console::Console(async_dispatcher_t* dispatcher, zx::eventpair event1, zx::eventpair event2,
                 RxSource rx_source, TxSink tx_sink)
    : dispatcher_(dispatcher),
      rx_fifo_(std::move(event1)),
      rx_event_(std::move(event2)),
      rx_source_(std::move(rx_source)),
      tx_sink_(std::move(tx_sink)),
      rx_thread_(std::thread([this]() { DebugReaderThread(); })) {}

Console::~Console() { rx_thread_.join(); }

void Console::Clone2(Clone2RequestView request, Clone2Completer::Sync& completer) {
  fidl::BindServer(dispatcher_,
                   fidl::ServerEnd<fuchsia_hardware_pty::Device>(request->request.TakeChannel()),
                   static_cast<fidl::WireServer<fuchsia_hardware_pty::Device>*>(this));
}

void Console::Close(CloseCompleter::Sync& completer) {
  completer.ReplySuccess();
  completer.Close(ZX_OK);
}

void Console::Query(QueryCompleter::Sync& completer) {
  const std::string_view kProtocol = fuchsia_hardware_pty::wire::kDeviceProtocolName;
  // TODO(https://fxbug.dev/42052765): avoid the const cast.
  uint8_t* data = reinterpret_cast<uint8_t*>(const_cast<char*>(kProtocol.data()));
  completer.Reply(fidl::VectorView<uint8_t>::FromExternal(data, kProtocol.size()));
}

void Console::Read(ReadRequestView request, ReadCompleter::Sync& completer) {
  // Don't try to read more than the FIFO can hold.
  uint64_t to_read = std::min<uint64_t>(request->count, Fifo::kFifoSize);
  uint8_t buf[to_read];
  size_t out_actual;
  if (zx_status_t status = rx_fifo_.Read(buf, to_read, &out_actual); status != ZX_OK) {
    completer.ReplyError(status);
  } else {
    completer.ReplySuccess(fidl::VectorView<uint8_t>::FromExternal(buf, out_actual));
  }
}

void Console::Write(WriteRequestView request, WriteCompleter::Sync& completer) {
  cpp20::span span = request->data.get();
  while (!span.empty()) {
    size_t count = std::min(span.size(), kMaxWriteSize);
    if (zx_status_t status = tx_sink_(span.data(), count); status != ZX_OK) {
      uint64_t written = std::distance(request->data.begin(), span.data());
      if (written != 0) {
        return completer.ReplySuccess(written);
      }
      return completer.ReplyError(status);
    }
    span = span.subspan(count);
  }
  return completer.ReplySuccess(request->data.count());
}

void Console::Describe(DescribeCompleter::Sync& completer) {
  zx::eventpair event;
  if (zx_status_t status = rx_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &event); status != ZX_OK) {
    completer.Close(status);
  } else {
    fidl::Arena alloc;
    completer.Reply(fuchsia_hardware_pty::wire::DeviceDescribeResponse::Builder(alloc)
                        .event(std::move(event))
                        .Build());
  }
}

void Console::OpenClient(OpenClientRequestView request, OpenClientCompleter::Sync& completer) {
  completer.Reply(ZX_ERR_NOT_SUPPORTED);
}
void Console::ClrSetFeature(ClrSetFeatureRequestView request,
                            ClrSetFeatureCompleter::Sync& completer) {
  completer.Reply(ZX_ERR_NOT_SUPPORTED, {});
}
void Console::GetWindowSize(GetWindowSizeCompleter::Sync& completer) {
  completer.Reply(ZX_ERR_NOT_SUPPORTED, {});
}
void Console::MakeActive(MakeActiveRequestView request, MakeActiveCompleter::Sync& completer) {
  completer.Reply(ZX_ERR_NOT_SUPPORTED);
}
void Console::ReadEvents(ReadEventsCompleter::Sync& completer) {
  completer.Reply(ZX_ERR_NOT_SUPPORTED, {});
}
void Console::SetWindowSize(SetWindowSizeRequestView request,
                            SetWindowSizeCompleter::Sync& completer) {
  completer.Reply(ZX_ERR_NOT_SUPPORTED);
}

void Console::DebugReaderThread() {
  while (true) {
    uint8_t ch;
    zx_status_t status = rx_source_(&ch);
    if (status != ZX_OK) {
      return;
    }
    size_t actual;
    rx_fifo_.Write(&ch, 1, &actual);
  }
}
