#include "pdx/client.h"

#include <log/log.h>

#include <pdx/trace.h>

namespace android {
namespace pdx {

void Client::EnableAutoReconnect(int64_t reconnect_timeout_ms) {
  if (channel_factory_) {
    reconnect_timeout_ms_ = reconnect_timeout_ms;
    auto_reconnect_enabled_ = true;
  }
}

void Client::DisableAutoReconnect() { auto_reconnect_enabled_ = false; }

bool Client::IsConnected() const { return channel_.get() != nullptr; }

Status<void> Client::CheckReconnect() {
  Status<void> ret;
  bool was_disconnected = !IsConnected();
  if (auto_reconnect_enabled_ && was_disconnected && channel_factory_) {
    auto status = channel_factory_->Connect(reconnect_timeout_ms_);
    if (!status) {
      error_ = -status.error();
      ret.SetError(status.error());
      return ret;
    }
    channel_ = status.take();
  }

  if (!IsConnected()) {
    ret.SetError(ESHUTDOWN);
  } else {
    // Call the subclass OnConnect handler. The subclass may choose to close the
    // connection in the handler, in which case error_ will be non-zero.
    if (was_disconnected)
      OnConnect();
    if (!IsConnected())
      ret.SetError(-error_);
    else
      ret.SetValue();
  }

  return ret;
}

bool Client::NeedToDisconnectChannel(int error) const {
  return error == ESHUTDOWN && auto_reconnect_enabled_;
}

void Client::CheckDisconnect(int error) {
  if (NeedToDisconnectChannel(error))
    Close(error);
}

Client::Client(std::unique_ptr<ClientChannel> channel)
    : channel_{std::move(channel)} {}

Client::Client(std::unique_ptr<ClientChannelFactory> channel_factory,
               int64_t timeout_ms)
    : channel_factory_{std::move(channel_factory)} {
  auto status = channel_factory_->Connect(timeout_ms);
  if (!status) {
    ALOGE("Client::Client: Failed to connect to service because: %s",
          status.GetErrorMessage().c_str());
    error_ = -status.error();
  } else {
    channel_ = status.take();
  }
}

bool Client::IsInitialized() const {
  return IsConnected() || (channel_factory_ && auto_reconnect_enabled_);
}

void Client::OnConnect() {}

int Client::error() const { return error_; }

Status<void> Client::SendImpulse(int opcode) {
  PDX_TRACE_NAME("Client::SendImpulse");

  auto status = CheckReconnect();
  if (!status)
    return status;

  status = channel_->SendImpulse(opcode, nullptr, 0);
  CheckDisconnect(status);
  return status;
}

Status<void> Client::SendImpulse(int opcode, const void* buffer,
                                 size_t length) {
  PDX_TRACE_NAME("Client::SendImpulse");

  auto status = CheckReconnect();
  if (!status)
    return status;

  status = channel_->SendImpulse(opcode, buffer, length);
  CheckDisconnect(status);
  return status;
}

void Client::Close(int error) {
  channel_.reset();
  // Normalize error codes to negative integer space.
  error_ = error <= 0 ? error : -error;
}

int Client::event_fd() const {
  return IsConnected() ? channel_->event_fd() : -1;
}

LocalChannelHandle& Client::GetChannelHandle() {
  return channel_->GetChannelHandle();
}

///////////////////////////// Transaction implementation //////////////////////

Transaction::Transaction(Client& client) : client_{client} {}

Transaction::~Transaction() {
  if (state_allocated_ && client_.GetChannel())
    client_.GetChannel()->FreeTransactionState(state_);
}

bool Transaction::EnsureStateAllocated() {
  if (!state_allocated_ && client_.GetChannel()) {
    state_ = client_.GetChannel()->AllocateTransactionState();
    state_allocated_ = true;
  }
  return state_allocated_;
}

void Transaction::SendTransaction(int opcode, Status<void>* ret,
                                  const iovec* send_vector, size_t send_count,
                                  const iovec* receive_vector,
                                  size_t receive_count) {
  *ret = client_.CheckReconnect();
  if (!*ret)
    return;

  if (!EnsureStateAllocated()) {
    ret->SetError(ESHUTDOWN);
    return;
  }

  auto status = client_.GetChannel()->SendWithInt(
      state_, opcode, send_vector, send_count, receive_vector, receive_count);

  if (status) {
    ret->SetValue();
  } else {
    ret->SetError(status.error());
  }
  CheckDisconnect(status);
}

void Transaction::SendTransaction(int opcode, Status<int>* ret,
                                  const iovec* send_vector, size_t send_count,
                                  const iovec* receive_vector,
                                  size_t receive_count) {
  auto status = client_.CheckReconnect();
  if (!status) {
    ret->SetError(status.error());
    return;
  }

  if (!EnsureStateAllocated()) {
    ret->SetError(ESHUTDOWN);
    return;
  }

  *ret = client_.GetChannel()->SendWithInt(
      state_, opcode, send_vector, send_count, receive_vector, receive_count);

  CheckDisconnect(*ret);
}

void Transaction::SendTransaction(int opcode, Status<LocalHandle>* ret,
                                  const iovec* send_vector, size_t send_count,
                                  const iovec* receive_vector,
                                  size_t receive_count) {
  auto status = client_.CheckReconnect();
  if (!status) {
    ret->SetError(status.error());
    return;
  }

  if (!EnsureStateAllocated()) {
    ret->SetError(ESHUTDOWN);
    return;
  }

  *ret = client_.GetChannel()->SendWithFileHandle(
      state_, opcode, send_vector, send_count, receive_vector, receive_count);

  CheckDisconnect(*ret);
}

void Transaction::SendTransaction(int opcode, Status<LocalChannelHandle>* ret,
                                  const iovec* send_vector, size_t send_count,
                                  const iovec* receive_vector,
                                  size_t receive_count) {
  auto status = client_.CheckReconnect();
  if (!status) {
    ret->SetError(status.error());
    return;
  }

  if (!EnsureStateAllocated()) {
    ret->SetError(ESHUTDOWN);
    return;
  }

  *ret = client_.GetChannel()->SendWithChannelHandle(
      state_, opcode, send_vector, send_count, receive_vector, receive_count);

  CheckDisconnect(*ret);
}

Status<FileReference> Transaction::PushFileHandle(const LocalHandle& handle) {
  if (client_.CheckReconnect() && EnsureStateAllocated())
    return client_.GetChannel()->PushFileHandle(state_, handle);
  return ErrorStatus{ESHUTDOWN};
}

Status<FileReference> Transaction::PushFileHandle(
    const BorrowedHandle& handle) {
  if (client_.CheckReconnect() && EnsureStateAllocated())
    return client_.GetChannel()->PushFileHandle(state_, handle);
  return ErrorStatus{ESHUTDOWN};
}

Status<FileReference> Transaction::PushFileHandle(const RemoteHandle& handle) {
  return handle.Get();
}

Status<ChannelReference> Transaction::PushChannelHandle(
    const LocalChannelHandle& handle) {
  if (client_.CheckReconnect() && EnsureStateAllocated())
    return client_.GetChannel()->PushChannelHandle(state_, handle);
  return ErrorStatus{ESHUTDOWN};
}

Status<ChannelReference> Transaction::PushChannelHandle(
    const BorrowedChannelHandle& handle) {
  if (client_.CheckReconnect() && EnsureStateAllocated())
    return client_.GetChannel()->PushChannelHandle(state_, handle);
  return ErrorStatus{ESHUTDOWN};
}

Status<ChannelReference> Transaction::PushChannelHandle(
    const RemoteChannelHandle& handle) {
  return handle.value();
}

bool Transaction::GetFileHandle(FileReference ref, LocalHandle* handle) {
  return client_.CheckReconnect() && EnsureStateAllocated() &&
         client_.GetChannel()->GetFileHandle(state_, ref, handle);
}

bool Transaction::GetChannelHandle(ChannelReference ref,
                                   LocalChannelHandle* handle) {
  return client_.CheckReconnect() && EnsureStateAllocated() &&
         client_.GetChannel()->GetChannelHandle(state_, ref, handle);
}

void Transaction::CheckDisconnect(int error) {
  if (client_.NeedToDisconnectChannel(error)) {
    if (state_allocated_) {
      if (client_.GetChannel())
        client_.GetChannel()->FreeTransactionState(state_);
      state_ = nullptr;
      state_allocated_ = false;
    }
    client_.Close(error);
  }
}

}  // namespace pdx
}  // namespace android
