#define LOG_TAG "ServiceFramework"
#include "pdx/service.h"

#include <fcntl.h>
#include <log/log.h>
#include <utils/misc.h>

#include <algorithm>
#include <cstdint>

#include <pdx/trace.h>

#define TRACE 0

namespace android {
namespace pdx {

std::shared_ptr<Channel> Channel::GetFromMessageInfo(const MessageInfo& info) {
  return info.channel ? info.channel->shared_from_this()
                      : std::shared_ptr<Channel>();
}

Message::Message() : replied_(true) {}

Message::Message(const MessageInfo& info)
    : service_{Service::GetFromMessageInfo(info)},
      channel_{Channel::GetFromMessageInfo(info)},
      info_{info},
      replied_{IsImpulse()} {
  auto svc = service_.lock();
  if (svc)
    state_ = svc->endpoint()->AllocateMessageState();
}

// C++11 specifies the move semantics for shared_ptr but not weak_ptr. This
// means we have to manually implement the desired move semantics for Message.
Message::Message(Message&& other) { *this = std::move(other); }

Message& Message::operator=(Message&& other) {
  Destroy();
  auto base = reinterpret_cast<std::uint8_t*>(&info_);
  std::fill(&base[0], &base[sizeof(info_)], 0);
  replied_ = true;
  std::swap(service_, other.service_);
  std::swap(channel_, other.channel_);
  std::swap(info_, other.info_);
  std::swap(state_, other.state_);
  std::swap(replied_, other.replied_);
  return *this;
}

Message::~Message() { Destroy(); }

void Message::Destroy() {
  auto svc = service_.lock();
  if (svc) {
    if (!replied_) {
      ALOGE(
          "ERROR: Service \"%s\" failed to reply to message: op=%d pid=%d "
          "cid=%d\n",
          svc->name_.c_str(), info_.op, info_.pid, info_.cid);
      svc->DefaultHandleMessage(*this);
    }
    svc->endpoint()->FreeMessageState(state_);
  }
  state_ = nullptr;
  service_.reset();
  channel_.reset();
}

const std::uint8_t* Message::ImpulseBegin() const {
  return reinterpret_cast<const std::uint8_t*>(info_.impulse);
}

const std::uint8_t* Message::ImpulseEnd() const {
  return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0);
}

Status<size_t> Message::ReadVector(const struct iovec* vector,
                                   size_t vector_length) {
  PDX_TRACE_NAME("Message::ReadVector");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->ReadMessageData(this, vector, vector_length);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<void> Message::ReadVectorAll(const struct iovec* vector,
                                    size_t vector_length) {
  PDX_TRACE_NAME("Message::ReadVectorAll");
  if (auto svc = service_.lock()) {
    const auto status =
        svc->endpoint()->ReadMessageData(this, vector, vector_length);
    if (!status)
      return status.error_status();
    size_t size_to_read = 0;
    for (size_t i = 0; i < vector_length; i++)
      size_to_read += vector[i].iov_len;
    if (status.get() < size_to_read)
      return ErrorStatus{EIO};
    return {};
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<size_t> Message::Read(void* buffer, size_t length) {
  PDX_TRACE_NAME("Message::Read");
  if (auto svc = service_.lock()) {
    const struct iovec vector = {buffer, length};
    return svc->endpoint()->ReadMessageData(this, &vector, 1);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<size_t> Message::WriteVector(const struct iovec* vector,
                                    size_t vector_length) {
  PDX_TRACE_NAME("Message::WriteVector");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->WriteMessageData(this, vector, vector_length);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<void> Message::WriteVectorAll(const struct iovec* vector,
                                     size_t vector_length) {
  PDX_TRACE_NAME("Message::WriteVector");
  if (auto svc = service_.lock()) {
    const auto status =
        svc->endpoint()->WriteMessageData(this, vector, vector_length);
    if (!status)
      return status.error_status();
    size_t size_to_write = 0;
    for (size_t i = 0; i < vector_length; i++)
      size_to_write += vector[i].iov_len;
    if (status.get() < size_to_write)
      return ErrorStatus{EIO};
    return {};
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<size_t> Message::Write(const void* buffer, size_t length) {
  PDX_TRACE_NAME("Message::Write");
  if (auto svc = service_.lock()) {
    const struct iovec vector = {const_cast<void*>(buffer), length};
    return svc->endpoint()->WriteMessageData(this, &vector, 1);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<FileReference> Message::PushFileHandle(const LocalHandle& handle) {
  PDX_TRACE_NAME("Message::PushFileHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushFileHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<FileReference> Message::PushFileHandle(const BorrowedHandle& handle) {
  PDX_TRACE_NAME("Message::PushFileHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushFileHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<FileReference> Message::PushFileHandle(const RemoteHandle& handle) {
  PDX_TRACE_NAME("Message::PushFileHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushFileHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<ChannelReference> Message::PushChannelHandle(
    const LocalChannelHandle& handle) {
  PDX_TRACE_NAME("Message::PushChannelHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushChannelHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<ChannelReference> Message::PushChannelHandle(
    const BorrowedChannelHandle& handle) {
  PDX_TRACE_NAME("Message::PushChannelHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushChannelHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<ChannelReference> Message::PushChannelHandle(
    const RemoteChannelHandle& handle) {
  PDX_TRACE_NAME("Message::PushChannelHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushChannelHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

bool Message::GetFileHandle(FileReference ref, LocalHandle* handle) {
  PDX_TRACE_NAME("Message::GetFileHandle");
  auto svc = service_.lock();
  if (!svc)
    return false;

  if (ref >= 0) {
    *handle = svc->endpoint()->GetFileHandle(this, ref);
    if (!handle->IsValid())
      return false;
  } else {
    *handle = LocalHandle{ref};
  }
  return true;
}

bool Message::GetChannelHandle(ChannelReference ref,
                               LocalChannelHandle* handle) {
  PDX_TRACE_NAME("Message::GetChannelHandle");
  auto svc = service_.lock();
  if (!svc)
    return false;

  if (ref >= 0) {
    *handle = svc->endpoint()->GetChannelHandle(this, ref);
    if (!handle->valid())
      return false;
  } else {
    *handle = LocalChannelHandle{nullptr, ref};
  }
  return true;
}

Status<void> Message::Reply(int return_code) {
  PDX_TRACE_NAME("Message::Reply");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReply(this, return_code);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::ReplyFileDescriptor(unsigned int fd) {
  PDX_TRACE_NAME("Message::ReplyFileDescriptor");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReplyFd(this, fd);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::ReplyError(unsigned int error) {
  PDX_TRACE_NAME("Message::ReplyError");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret =
        svc->endpoint()->MessageReply(this, -static_cast<int>(error));
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const LocalHandle& handle) {
  PDX_TRACE_NAME("Message::ReplyFileHandle");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    Status<void> ret;

    if (handle)
      ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
    else
      ret = svc->endpoint()->MessageReply(this, handle.Get());

    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const BorrowedHandle& handle) {
  PDX_TRACE_NAME("Message::ReplyFileHandle");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    Status<void> ret;

    if (handle)
      ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
    else
      ret = svc->endpoint()->MessageReply(this, handle.Get());

    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const RemoteHandle& handle) {
  PDX_TRACE_NAME("Message::ReplyFileHandle");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    Status<void> ret;

    if (handle)
      ret = svc->endpoint()->MessageReply(this, handle.Get());
    else
      ret = svc->endpoint()->MessageReply(this, handle.Get());

    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const LocalChannelHandle& handle) {
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const BorrowedChannelHandle& handle) {
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const RemoteChannelHandle& handle) {
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) {
  PDX_TRACE_NAME("Message::ModifyChannelEvents");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask,
                                                set_mask);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<RemoteChannelHandle> Message::PushChannel(
    int flags, const std::shared_ptr<Channel>& channel, int* channel_id) {
  PDX_TRACE_NAME("Message::PushChannel");
  if (auto svc = service_.lock()) {
    return svc->PushChannel(this, flags, channel, channel_id);
  } else {
    return ErrorStatus(ESHUTDOWN);
  }
}

Status<RemoteChannelHandle> Message::PushChannel(
    Service* service, int flags, const std::shared_ptr<Channel>& channel,
    int* channel_id) {
  PDX_TRACE_NAME("Message::PushChannel");
  return service->PushChannel(this, flags, channel, channel_id);
}

Status<int> Message::CheckChannel(ChannelReference ref,
                                  std::shared_ptr<Channel>* channel) const {
  PDX_TRACE_NAME("Message::CheckChannel");
  if (auto svc = service_.lock()) {
    return svc->CheckChannel(this, ref, channel);
  } else {
    return ErrorStatus(ESHUTDOWN);
  }
}

Status<int> Message::CheckChannel(const Service* service, ChannelReference ref,
                                  std::shared_ptr<Channel>* channel) const {
  PDX_TRACE_NAME("Message::CheckChannel");
  return service->CheckChannel(this, ref, channel);
}

pid_t Message::GetProcessId() const { return info_.pid; }

pid_t Message::GetThreadId() const { return info_.tid; }

uid_t Message::GetEffectiveUserId() const { return info_.euid; }

gid_t Message::GetEffectiveGroupId() const { return info_.egid; }

int Message::GetChannelId() const { return info_.cid; }

int Message::GetMessageId() const { return info_.mid; }

int Message::GetOp() const { return info_.op; }

int Message::GetFlags() const { return info_.flags; }

size_t Message::GetSendLength() const { return info_.send_len; }

size_t Message::GetReceiveLength() const { return info_.recv_len; }

size_t Message::GetFileDescriptorCount() const { return info_.fd_count; }

std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); }

Status<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) {
  channel_ = chan;
  Status<void> status;
  if (auto svc = service_.lock())
    status = svc->SetChannel(info_.cid, chan);
  return status;
}

std::shared_ptr<Service> Message::GetService() const { return service_.lock(); }

const MessageInfo& Message::GetInfo() const { return info_; }

Service::Service(const std::string& name, std::unique_ptr<Endpoint> endpoint)
    : name_(name), endpoint_{std::move(endpoint)} {
  if (!endpoint_)
    return;

  const auto status = endpoint_->SetService(this);
  ALOGE_IF(!status, "Failed to set service context because: %s",
           status.GetErrorMessage().c_str());
}

Service::~Service() {
  if (endpoint_) {
    const auto status = endpoint_->SetService(nullptr);
    ALOGE_IF(!status, "Failed to clear service context because: %s",
             status.GetErrorMessage().c_str());
  }
}

std::shared_ptr<Service> Service::GetFromMessageInfo(const MessageInfo& info) {
  return info.service ? info.service->shared_from_this()
                      : std::shared_ptr<Service>();
}

bool Service::IsInitialized() const { return endpoint_.get() != nullptr; }

std::shared_ptr<Channel> Service::OnChannelOpen(Message& /*message*/) {
  return nullptr;
}

void Service::OnChannelClose(Message& /*message*/,
                             const std::shared_ptr<Channel>& /*channel*/) {}

Status<void> Service::SetChannel(int channel_id,
                                 const std::shared_ptr<Channel>& channel) {
  PDX_TRACE_NAME("Service::SetChannel");
  std::lock_guard<std::mutex> autolock(channels_mutex_);

  const auto status = endpoint_->SetChannel(channel_id, channel.get());
  if (!status) {
    ALOGE("%s::SetChannel: Failed to set channel context: %s\n", name_.c_str(),
          status.GetErrorMessage().c_str());

    // It's possible someone mucked with things behind our back by calling the C
    // API directly. Since we know the channel id isn't valid, make sure we
    // don't have it in the channels map.
    if (status.error() == ENOENT)
      channels_.erase(channel_id);
  } else {
    if (channel != nullptr)
      channels_[channel_id] = channel;
    else
      channels_.erase(channel_id);
  }
  return status;
}

std::shared_ptr<Channel> Service::GetChannel(int channel_id) const {
  PDX_TRACE_NAME("Service::GetChannel");
  std::lock_guard<std::mutex> autolock(channels_mutex_);

  auto search = channels_.find(channel_id);
  if (search != channels_.end())
    return search->second;
  else
    return nullptr;
}

Status<void> Service::CloseChannel(int channel_id) {
  PDX_TRACE_NAME("Service::CloseChannel");
  std::lock_guard<std::mutex> autolock(channels_mutex_);

  const auto status = endpoint_->CloseChannel(channel_id);

  // Always erase the map entry, in case someone mucked with things behind our
  // back using the C API directly.
  channels_.erase(channel_id);

  return status;
}

Status<void> Service::ModifyChannelEvents(int channel_id, int clear_mask,
                                          int set_mask) {
  PDX_TRACE_NAME("Service::ModifyChannelEvents");
  return endpoint_->ModifyChannelEvents(channel_id, clear_mask, set_mask);
}

Status<RemoteChannelHandle> Service::PushChannel(
    Message* message, int flags, const std::shared_ptr<Channel>& channel,
    int* channel_id) {
  PDX_TRACE_NAME("Service::PushChannel");

  std::lock_guard<std::mutex> autolock(channels_mutex_);

  int channel_id_temp = -1;
  Status<RemoteChannelHandle> ret =
      endpoint_->PushChannel(message, flags, channel.get(), &channel_id_temp);
  ALOGE_IF(!ret.ok(), "%s::PushChannel: Failed to push channel: %s",
           name_.c_str(), strerror(ret.error()));

  if (channel && channel_id_temp != -1)
    channels_[channel_id_temp] = channel;
  if (channel_id)
    *channel_id = channel_id_temp;

  return ret;
}

Status<int> Service::CheckChannel(const Message* message, ChannelReference ref,
                                  std::shared_ptr<Channel>* channel) const {
  PDX_TRACE_NAME("Service::CheckChannel");

  // Synchronization to maintain consistency between the kernel's channel
  // context pointer and the userspace channels_ map. Other threads may attempt
  // to modify the map at the same time, which could cause the channel context
  // pointer returned by the kernel to be invalid.
  std::lock_guard<std::mutex> autolock(channels_mutex_);

  Channel* channel_context = nullptr;
  Status<int> ret = endpoint_->CheckChannel(
      message, ref, channel ? &channel_context : nullptr);
  if (ret && channel) {
    if (channel_context)
      *channel = channel_context->shared_from_this();
    else
      *channel = nullptr;
  }

  return ret;
}

std::string Service::DumpState(size_t /*max_length*/) { return ""; }

Status<void> Service::HandleMessage(Message& message) {
  return DefaultHandleMessage(message);
}

void Service::HandleImpulse(Message& /*impulse*/) {}

Status<void> Service::HandleSystemMessage(Message& message) {
  const MessageInfo& info = message.GetInfo();

  switch (info.op) {
    case opcodes::CHANNEL_OPEN: {
      ALOGD("%s::OnChannelOpen: pid=%d cid=%d\n", name_.c_str(), info.pid,
            info.cid);
      message.SetChannel(OnChannelOpen(message));
      return message.Reply(0);
    }

    case opcodes::CHANNEL_CLOSE: {
      ALOGD("%s::OnChannelClose: pid=%d cid=%d\n", name_.c_str(), info.pid,
            info.cid);
      OnChannelClose(message, Channel::GetFromMessageInfo(info));
      message.SetChannel(nullptr);
      return message.Reply(0);
    }

    case opcodes::REPORT_SYSPROP_CHANGE:
      ALOGD("%s:REPORT_SYSPROP_CHANGE: pid=%d cid=%d\n", name_.c_str(),
            info.pid, info.cid);
      OnSysPropChange();
      android::report_sysprop_change();
      return message.Reply(0);

    case opcodes::DUMP_STATE: {
      ALOGD("%s:DUMP_STATE: pid=%d cid=%d\n", name_.c_str(), info.pid,
            info.cid);
      auto response = DumpState(message.GetReceiveLength());
      const size_t response_size = response.size() < message.GetReceiveLength()
                                       ? response.size()
                                       : message.GetReceiveLength();
      const Status<size_t> status =
          message.Write(response.data(), response_size);
      if (status && status.get() < response_size)
        return message.ReplyError(EIO);
      else
        return message.Reply(status);
    }

    default:
      return ErrorStatus{EOPNOTSUPP};
  }
}

Status<void> Service::DefaultHandleMessage(Message& message) {
  const MessageInfo& info = message.GetInfo();

  ALOGD_IF(TRACE, "Service::DefaultHandleMessage: pid=%d cid=%d op=%d\n",
           info.pid, info.cid, info.op);

  switch (info.op) {
    case opcodes::CHANNEL_OPEN:
    case opcodes::CHANNEL_CLOSE:
    case opcodes::REPORT_SYSPROP_CHANGE:
    case opcodes::DUMP_STATE:
      return HandleSystemMessage(message);

    default:
      return message.ReplyError(EOPNOTSUPP);
  }
}

void Service::OnSysPropChange() {}

Status<void> Service::ReceiveAndDispatch() {
  Message message;
  const auto status = endpoint_->MessageReceive(&message);
  if (!status) {
    ALOGE("Failed to receive message: %s\n", status.GetErrorMessage().c_str());
    return status;
  }

  std::shared_ptr<Service> service = message.GetService();

  if (!service) {
    ALOGE("Service::ReceiveAndDispatch: service context is NULL!!!\n");
    // Don't block the sender indefinitely in this error case.
    endpoint_->MessageReply(&message, -EINVAL);
    return ErrorStatus{EINVAL};
  }

  if (message.IsImpulse()) {
    service->HandleImpulse(message);
    return {};
  } else if (service->HandleSystemMessage(message)) {
    return {};
  } else {
    return service->HandleMessage(message);
  }
}

Status<void> Service::Cancel() { return endpoint_->Cancel(); }

}  // namespace pdx
}  // namespace android
