#include "pdx/client.h"

#define LOG_TAG "ServiceFramework"
#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
