#include "uds/client_channel.h"

#include <errno.h>
#include <log/log.h>
#include <sys/epoll.h>
#include <sys/socket.h>

#include <pdx/client.h>
#include <pdx/service_endpoint.h>
#include <uds/ipc_helper.h>

namespace android {
namespace pdx {
namespace uds {

namespace {

struct TransactionState {
  bool GetLocalFileHandle(int index, LocalHandle* handle) {
    if (index < 0) {
      handle->Reset(index);
    } else if (static_cast<size_t>(index) < response.file_descriptors.size()) {
      *handle = std::move(response.file_descriptors[index]);
    } else {
      return false;
    }
    return true;
  }

  bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) {
    if (index < 0) {
      *handle = LocalChannelHandle{nullptr, index};
    } else if (static_cast<size_t>(index) < response.channels.size()) {
      auto& channel_info = response.channels[index];
      *handle = ChannelManager::Get().CreateHandle(
          std::move(channel_info.data_fd),
          std::move(channel_info.pollin_event_fd),
          std::move(channel_info.pollhup_event_fd));
    } else {
      return false;
    }
    return true;
  }

  FileReference PushFileHandle(BorrowedHandle handle) {
    if (!handle)
      return handle.Get();
    request.file_descriptors.push_back(std::move(handle));
    return request.file_descriptors.size() - 1;
  }

  ChannelReference PushChannelHandle(BorrowedChannelHandle handle) {
    if (!handle)
      return handle.value();

    if (auto* channel_data =
            ChannelManager::Get().GetChannelData(handle.value())) {
      ChannelInfo<BorrowedHandle> channel_info{
          channel_data->data_fd(), channel_data->pollin_event_fd(),
          channel_data->pollhup_event_fd()};
      request.channels.push_back(std::move(channel_info));
      return request.channels.size() - 1;
    } else {
      return -1;
    }
  }

  RequestHeader<BorrowedHandle> request;
  ResponseHeader<LocalHandle> response;
};

Status<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
  while (size > 0) {
    // If there is more data to read in the message than the buffers provided
    // by the caller, read and discard the extra data from the socket.
    char buffer[1024];
    size_t size_to_read = std::min(sizeof(buffer), size);
    auto status = ReceiveData(socket_fd, buffer, size_to_read);
    if (!status)
      return status;
    size -= size_to_read;
  }
  // We still want to return EIO error to the caller in case we had unexpected
  // data in the socket stream.
  return ErrorStatus(EIO);
}

Status<void> SendRequest(const BorrowedHandle& socket_fd,
                         TransactionState* transaction_state, int opcode,
                         const iovec* send_vector, size_t send_count,
                         size_t max_recv_len) {
  size_t send_len = CountVectorSize(send_vector, send_count);
  InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
              false);
  if (send_len == 0) {
    send_vector = nullptr;
    send_count = 0;
  }
  return SendData(socket_fd, transaction_state->request, send_vector,
                  send_count);
}

Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
                             TransactionState* transaction_state,
                             const iovec* receive_vector, size_t receive_count,
                             size_t max_recv_len) {
  auto status = ReceiveData(socket_fd, &transaction_state->response);
  if (!status)
    return status;

  if (transaction_state->response.recv_len > 0) {
    std::vector<iovec> read_buffers;
    size_t size_remaining = 0;
    if (transaction_state->response.recv_len != max_recv_len) {
      // If the receive buffer not exactly the size of data available, recreate
      // the vector list to consume the data exactly since ReceiveDataVector()
      // validates that the number of bytes received equals the number of bytes
      // requested.
      size_remaining = transaction_state->response.recv_len;
      for (size_t i = 0; i < receive_count && size_remaining > 0; i++) {
        read_buffers.push_back(receive_vector[i]);
        iovec& last_vec = read_buffers.back();
        if (last_vec.iov_len > size_remaining)
          last_vec.iov_len = size_remaining;
        size_remaining -= last_vec.iov_len;
      }
      receive_vector = read_buffers.data();
      receive_count = read_buffers.size();
    }
    status = ReceiveDataVector(socket_fd, receive_vector, receive_count);
    if (status && size_remaining > 0)
      status = ReadAndDiscardData(socket_fd, size_remaining);
  }
  return status;
}

}  // anonymous namespace

ClientChannel::ClientChannel(LocalChannelHandle channel_handle)
    : channel_handle_{std::move(channel_handle)} {
  channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value());
}

std::unique_ptr<pdx::ClientChannel> ClientChannel::Create(
    LocalChannelHandle channel_handle) {
  return std::unique_ptr<pdx::ClientChannel>{
      new ClientChannel{std::move(channel_handle)}};
}

ClientChannel::~ClientChannel() {
  if (channel_handle_)
    shutdown(channel_handle_.value(), SHUT_WR);
}

void* ClientChannel::AllocateTransactionState() { return new TransactionState; }

void ClientChannel::FreeTransactionState(void* state) {
  delete static_cast<TransactionState*>(state);
}

Status<void> ClientChannel::SendImpulse(int opcode, const void* buffer,
                                        size_t length) {
  std::unique_lock<std::mutex> lock(socket_mutex_);
  Status<void> status;
  android::pdx::uds::RequestHeader<BorrowedHandle> request;
  if (length > request.impulse_payload.size() ||
      (buffer == nullptr && length != 0)) {
    status.SetError(EINVAL);
    return status;
  }

  InitRequest(&request, opcode, length, 0, true);
  memcpy(request.impulse_payload.data(), buffer, length);
  return SendData(BorrowedHandle{channel_handle_.value()}, request);
}

Status<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
                                          const iovec* send_vector,
                                          size_t send_count,
                                          const iovec* receive_vector,
                                          size_t receive_count) {
  std::unique_lock<std::mutex> lock(socket_mutex_);
  Status<int> result;
  if ((send_vector == nullptr && send_count != 0) ||
      (receive_vector == nullptr && receive_count != 0)) {
    result.SetError(EINVAL);
    return result;
  }

  auto* state = static_cast<TransactionState*>(transaction_state);
  size_t max_recv_len = CountVectorSize(receive_vector, receive_count);

  auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
                            opcode, send_vector, send_count, max_recv_len);
  if (status) {
    status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
                             receive_vector, receive_count, max_recv_len);
  }
  if (!result.PropagateError(status)) {
    const int return_code = state->response.ret_code;
    if (return_code >= 0)
      result.SetValue(return_code);
    else
      result.SetError(-return_code);
  }
  return result;
}

Status<int> ClientChannel::SendWithInt(void* transaction_state, int opcode,
                                       const iovec* send_vector,
                                       size_t send_count,
                                       const iovec* receive_vector,
                                       size_t receive_count) {
  return SendAndReceive(transaction_state, opcode, send_vector, send_count,
                        receive_vector, receive_count);
}

Status<LocalHandle> ClientChannel::SendWithFileHandle(
    void* transaction_state, int opcode, const iovec* send_vector,
    size_t send_count, const iovec* receive_vector, size_t receive_count) {
  Status<int> int_status =
      SendAndReceive(transaction_state, opcode, send_vector, send_count,
                     receive_vector, receive_count);
  Status<LocalHandle> status;
  if (status.PropagateError(int_status))
    return status;

  auto* state = static_cast<TransactionState*>(transaction_state);
  LocalHandle handle;
  if (state->GetLocalFileHandle(int_status.get(), &handle)) {
    status.SetValue(std::move(handle));
  } else {
    status.SetError(EINVAL);
  }
  return status;
}

Status<LocalChannelHandle> ClientChannel::SendWithChannelHandle(
    void* transaction_state, int opcode, const iovec* send_vector,
    size_t send_count, const iovec* receive_vector, size_t receive_count) {
  Status<int> int_status =
      SendAndReceive(transaction_state, opcode, send_vector, send_count,
                     receive_vector, receive_count);
  Status<LocalChannelHandle> status;
  if (status.PropagateError(int_status))
    return status;

  auto* state = static_cast<TransactionState*>(transaction_state);
  LocalChannelHandle handle;
  if (state->GetLocalChannelHandle(int_status.get(), &handle)) {
    status.SetValue(std::move(handle));
  } else {
    status.SetError(EINVAL);
  }
  return status;
}

FileReference ClientChannel::PushFileHandle(void* transaction_state,
                                            const LocalHandle& handle) {
  auto* state = static_cast<TransactionState*>(transaction_state);
  return state->PushFileHandle(handle.Borrow());
}

FileReference ClientChannel::PushFileHandle(void* transaction_state,
                                            const BorrowedHandle& handle) {
  auto* state = static_cast<TransactionState*>(transaction_state);
  return state->PushFileHandle(handle.Duplicate());
}

ChannelReference ClientChannel::PushChannelHandle(
    void* transaction_state, const LocalChannelHandle& handle) {
  auto* state = static_cast<TransactionState*>(transaction_state);
  return state->PushChannelHandle(handle.Borrow());
}

ChannelReference ClientChannel::PushChannelHandle(
    void* transaction_state, const BorrowedChannelHandle& handle) {
  auto* state = static_cast<TransactionState*>(transaction_state);
  return state->PushChannelHandle(handle.Duplicate());
}

bool ClientChannel::GetFileHandle(void* transaction_state, FileReference ref,
                                  LocalHandle* handle) const {
  auto* state = static_cast<TransactionState*>(transaction_state);
  return state->GetLocalFileHandle(ref, handle);
}

bool ClientChannel::GetChannelHandle(void* transaction_state,
                                     ChannelReference ref,
                                     LocalChannelHandle* handle) const {
  auto* state = static_cast<TransactionState*>(transaction_state);
  return state->GetLocalChannelHandle(ref, handle);
}

}  // namespace uds
}  // namespace pdx
}  // namespace android
