#define LOG_TAG "PoseClient"
#include <dvr/pose_client.h>

#include <stdint.h>

#include <base/logging.h>
#include <cutils/log.h>
#include <pdx/client.h>
#include <pdx/default_transport/client_channel_factory.h>
#include <pdx/file_handle.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/pose-ipc.h>
#include <private/dvr/pose_client_internal.h>
#include <private/dvr/sensor_constants.h>

using android::pdx::LocalHandle;
using android::pdx::LocalChannelHandle;
using android::pdx::Status;
using android::pdx::Transaction;

namespace android {
namespace dvr {

// PoseClient is a remote interface to the pose service in sensord.
class PoseClient : public pdx::ClientBase<PoseClient> {
 public:
  ~PoseClient() override {}

  // Casts C handle into an instance of this class.
  static PoseClient* FromC(DvrPose* client) {
    return reinterpret_cast<PoseClient*>(client);
  }

  // Polls the pose service for the current state and stores it in *state.
  // Returns zero on success, a negative error code otherwise.
  int Poll(DvrPoseState* state) {
    Transaction trans{*this};
    Status<int> status =
        trans.Send<int>(DVR_POSE_POLL, nullptr, 0, state, sizeof(*state));
    ALOGE_IF(!status, "Pose poll() failed because: %s\n",
             status.GetErrorMessage().c_str());
    return ReturnStatusOrError(status);
  }

  int GetPose(uint32_t vsync_count, DvrPoseAsync* out_pose) {
    if (!mapped_pose_buffer_) {
      int ret = GetRingBuffer(nullptr);
      if (ret < 0)
        return ret;
    }
    *out_pose =
        mapped_pose_buffer_->ring[vsync_count & kPoseAsyncBufferIndexMask];
    return 0;
  }

  uint32_t GetVsyncCount() {
    if (!mapped_pose_buffer_) {
      int ret = GetRingBuffer(nullptr);
      if (ret < 0)
        return 0;
    }
    return mapped_pose_buffer_->vsync_count;
  }

  int GetControllerPose(int32_t controller_id, uint32_t vsync_count,
                        DvrPoseAsync* out_pose) {
    if (controller_id < 0 ||
        controller_id >= static_cast<int32_t>(arraysize(controllers_))) {
      return -EINVAL;
    }
    if (!controllers_[controller_id].mapped_pose_buffer) {
      int ret = GetControllerRingBuffer(controller_id);
      if (ret < 0)
        return ret;
    }
    *out_pose =
        controllers_[controller_id]
            .mapped_pose_buffer[vsync_count & kPoseAsyncBufferIndexMask];
    return 0;
  }

  int LogController(bool enable) {
    Transaction trans{*this};
    Status<int> status = trans.Send<int>(DVR_POSE_LOG_CONTROLLER, &enable,
                                         sizeof(enable), nullptr, 0);
    ALOGE_IF(!status, "Pose LogController() failed because: %s",
             status.GetErrorMessage().c_str());
    return ReturnStatusOrError(status);
  }

  // Freezes the pose to the provided state. Future poll operations will return
  // this state until a different state is frozen or SetMode() is called with a
  // different mode.
  // Returns zero on success, a negative error code otherwise.
  int Freeze(const DvrPoseState& frozen_state) {
    Transaction trans{*this};
    Status<int> status = trans.Send<int>(DVR_POSE_FREEZE, &frozen_state,
                                         sizeof(frozen_state), nullptr, 0);
    ALOGE_IF(!status, "Pose Freeze() failed because: %s\n",
             status.GetErrorMessage().c_str());
    return ReturnStatusOrError(status);
  }

  // Sets the data mode for the pose service.
  int SetMode(DvrPoseMode mode) {
    Transaction trans{*this};
    Status<int> status =
        trans.Send<int>(DVR_POSE_SET_MODE, &mode, sizeof(mode), nullptr, 0);
    ALOGE_IF(!status, "Pose SetPoseMode() failed because: %s",
             status.GetErrorMessage().c_str());
    return ReturnStatusOrError(status);
  }

  // Gets the data mode for the pose service.
  int GetMode(DvrPoseMode* out_mode) {
    int mode;
    Transaction trans{*this};
    Status<int> status =
        trans.Send<int>(DVR_POSE_GET_MODE, nullptr, 0, &mode, sizeof(mode));
    ALOGE_IF(!status, "Pose GetPoseMode() failed because: %s",
             status.GetErrorMessage().c_str());
    if (status)
      *out_mode = DvrPoseMode(mode);
    return ReturnStatusOrError(status);
  }

  int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
    if (pose_buffer_.get()) {
      if (out_info) {
        GetPoseRingBufferInfo(out_info);
      }
      return 0;
    }

    Transaction trans{*this};
    Status<LocalChannelHandle> status =
        trans.Send<LocalChannelHandle>(DVR_POSE_GET_RING_BUFFER);
    if (!status) {
      ALOGE("Pose GetRingBuffer() failed because: %s",
            status.GetErrorMessage().c_str());
      return -status.error();
    }

    auto buffer = BufferConsumer::Import(status.take());
    if (!buffer) {
      ALOGE("Pose failed to import ring buffer");
      return -EIO;
    }
    void* addr = nullptr;
    int ret = buffer->GetBlobReadOnlyPointer(sizeof(DvrPoseRingBuffer), &addr);
    if (ret < 0 || !addr) {
      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
      return -EIO;
    }
    pose_buffer_.swap(buffer);
    mapped_pose_buffer_ = static_cast<const DvrPoseRingBuffer*>(addr);
    LOG(INFO) << "Mapped pose data translation "
              << mapped_pose_buffer_->ring[0].translation[0] << ','
              << mapped_pose_buffer_->ring[0].translation[1] << ','
              << mapped_pose_buffer_->ring[0].translation[2] << ", quat "
              << mapped_pose_buffer_->ring[0].orientation[0] << ','
              << mapped_pose_buffer_->ring[0].orientation[1] << ','
              << mapped_pose_buffer_->ring[0].orientation[2] << ','
              << mapped_pose_buffer_->ring[0].orientation[3];
    if (out_info) {
      GetPoseRingBufferInfo(out_info);
    }
    return 0;
  }

  int GetControllerRingBuffer(int32_t controller_id) {
    if (controller_id < 0 ||
        controller_id >= static_cast<int32_t>(arraysize(controllers_))) {
      return -EINVAL;
    }
    ControllerClientState& client_state = controllers_[controller_id];
    if (client_state.pose_buffer.get()) {
      return 0;
    }

    Transaction trans{*this};
    Status<LocalChannelHandle> status = trans.Send<LocalChannelHandle>(
        DVR_POSE_GET_CONTROLLER_RING_BUFFER, &controller_id,
        sizeof(controller_id), nullptr, 0);
    if (!status) {
      ALOGE("Pose GetControllerRingBuffer() failed because: %s",
            status.GetErrorMessage().c_str());
      return -status.error();
    }

    auto buffer = BufferConsumer::Import(status.take());
    if (!buffer) {
      ALOGE("Pose failed to import ring buffer");
      return -EIO;
    }
    constexpr size_t size = kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync);
    void* addr = nullptr;
    int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
    if (ret < 0 || !addr) {
      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
      return -EIO;
    }
    client_state.pose_buffer.swap(buffer);
    client_state.mapped_pose_buffer = static_cast<const DvrPoseAsync*>(addr);
    LOG(INFO) << "Mapped controller " << controller_id
              << " pose data translation "
              << client_state.mapped_pose_buffer[0].translation[0] << ','
              << client_state.mapped_pose_buffer[0].translation[1] << ','
              << client_state.mapped_pose_buffer[0].translation[2] << ", quat "
              << client_state.mapped_pose_buffer[0].orientation[0] << ','
              << client_state.mapped_pose_buffer[0].orientation[1] << ','
              << client_state.mapped_pose_buffer[0].orientation[2] << ','
              << client_state.mapped_pose_buffer[0].orientation[3];
    return 0;
  }

  int NotifyVsync(uint32_t vsync_count, int64_t display_timestamp,
                  int64_t display_period_ns,
                  int64_t right_eye_photon_offset_ns) {
    const struct iovec data[] = {
        {.iov_base = &vsync_count, .iov_len = sizeof(vsync_count)},
        {.iov_base = &display_timestamp, .iov_len = sizeof(display_timestamp)},
        {.iov_base = &display_period_ns, .iov_len = sizeof(display_period_ns)},
        {.iov_base = &right_eye_photon_offset_ns,
         .iov_len = sizeof(right_eye_photon_offset_ns)},
    };
    Transaction trans{*this};
    Status<int> status =
        trans.SendVector<int>(DVR_POSE_NOTIFY_VSYNC, data, nullptr);
    ALOGE_IF(!status, "Pose NotifyVsync() failed because: %s\n",
             status.GetErrorMessage().c_str());
    return ReturnStatusOrError(status);
  }

  int GetRingBufferFd(LocalHandle* fd) {
    int ret = GetRingBuffer(nullptr);
    if (ret < 0)
      return ret;
    *fd = pose_buffer_->GetBlobFd();
    return 0;
  }

 private:
  friend BASE;

  // Set up a channel to the pose service.
  PoseClient()
      : BASE(pdx::default_transport::ClientChannelFactory::Create(
            DVR_POSE_SERVICE_CLIENT)) {
    // TODO(eieio): Cache the pose and make timeout 0 so that the API doesn't
    // block while waiting for the pose service to come back up.
    EnableAutoReconnect(kInfiniteTimeout);
  }

  PoseClient(const PoseClient&) = delete;
  PoseClient& operator=(const PoseClient&) = delete;

  void GetPoseRingBufferInfo(DvrPoseRingBufferInfo* out_info) const {
    out_info->min_future_count = kPoseAsyncBufferMinFutureCount;
    out_info->total_count = kPoseAsyncBufferTotalCount;
    out_info->buffer = mapped_pose_buffer_->ring;
  }

  std::unique_ptr<BufferConsumer> pose_buffer_;
  const DvrPoseRingBuffer* mapped_pose_buffer_ = nullptr;

  struct ControllerClientState {
    std::unique_ptr<BufferConsumer> pose_buffer;
    const DvrPoseAsync* mapped_pose_buffer = nullptr;
  };
  ControllerClientState controllers_[2];
};

}  // namespace dvr
}  // namespace android

using android::dvr::PoseClient;

struct DvrPose {};

extern "C" {

DvrPose* dvrPoseCreate() {
  PoseClient* client = PoseClient::Create().release();
  return reinterpret_cast<DvrPose*>(client);
}

void dvrPoseDestroy(DvrPose* client) { delete PoseClient::FromC(client); }

int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose) {
  return PoseClient::FromC(client)->GetPose(vsync_count, out_pose);
}

uint32_t dvrPoseGetVsyncCount(DvrPose* client) {
  return PoseClient::FromC(client)->GetVsyncCount();
}

int dvrPoseGetController(DvrPose* client, int32_t controller_id,
                         uint32_t vsync_count, DvrPoseAsync* out_pose) {
  return PoseClient::FromC(client)->GetControllerPose(controller_id,
                                                      vsync_count, out_pose);
}

int dvrPoseLogController(DvrPose* client, bool enable) {
  return PoseClient::FromC(client)->LogController(enable);
}

int dvrPosePoll(DvrPose* client, DvrPoseState* state) {
  return PoseClient::FromC(client)->Poll(state);
}

int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state) {
  return PoseClient::FromC(client)->Freeze(*frozen_state);
}

int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode) {
  return PoseClient::FromC(client)->SetMode(mode);
}

int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode) {
  return PoseClient::FromC(client)->GetMode(mode);
}

int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info) {
  return PoseClient::FromC(client)->GetRingBuffer(out_info);
}

int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
                              int64_t display_timestamp,
                              int64_t display_period_ns,
                              int64_t right_eye_photon_offset_ns) {
  return PoseClient::FromC(client)->NotifyVsync(vsync_count, display_timestamp,
                                                display_period_ns,
                                                right_eye_photon_offset_ns);
}

int privateDvrPoseGetRingBufferFd(DvrPose* client, LocalHandle* fd) {
  return PoseClient::FromC(client)->GetRingBufferFd(fd);
}

}  // extern "C"
