// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_i2c/register_device.h"

#include "pw_assert/check.h"
#include "pw_bytes/byte_builder.h"

namespace pw {
namespace i2c {
namespace {

// Puts the register address data into the buffer based on the size of the
// register address.
void PutRegisterAddressInByteBuilder(
    ByteBuilder& byte_builder,
    const uint32_t register_address,
    const std::endian order,
    RegisterAddressSize register_address_size) {
  // TODO(b/185952662): Simplify the call site by extending the byte builder
  //                   and endian API.
  switch (register_address_size) {
    case RegisterAddressSize::k1Byte:
      byte_builder.PutUint8(static_cast<uint8_t>(register_address));
      break;

    case RegisterAddressSize::k2Bytes:
      byte_builder.PutUint16(static_cast<uint16_t>(register_address), order);
      break;

    case RegisterAddressSize::k4Bytes:
      byte_builder.PutUint32(register_address, order);
      break;

    default:
      PW_CRASH("Invalid address size being put in byte buffer");
  }
}

void PutRegisterData16InByteBuilder(ByteBuilder& byte_builder,
                                    ConstByteSpan register_data,
                                    const std::endian order) {
  uint32_t data_pointer_index = 0;

  while (data_pointer_index < register_data.size()) {
    const uint16_t data = *reinterpret_cast<const uint16_t*>(
        register_data.data() + data_pointer_index);
    byte_builder.PutUint16(data, order);
    data_pointer_index += sizeof(data);
  }
}

Status PutRegisterData32InByteBuilder(ByteBuilder& byte_builder,
                                      ConstByteSpan register_data,
                                      const std::endian order) {
  uint32_t data_pointer_index = 0;

  while (data_pointer_index < register_data.size()) {
    const uint32_t data = *reinterpret_cast<const uint32_t*>(
        register_data.data() + data_pointer_index);
    byte_builder.PutUint32(data, order);
    data_pointer_index += sizeof(data);
  }

  if (data_pointer_index == register_data.size()) {
    return pw::OkStatus();
  } else {
    // The write data that was given doesn't align with the expected register
    // data size.
    return Status::InvalidArgument();
  }
}

}  // namespace

Status RegisterDevice::WriteRegisters(
    const uint32_t register_address,
    ConstByteSpan register_data,
    const size_t register_data_size,
    ByteSpan buffer,
    chrono::SystemClock::duration for_at_least) {
  // Make sure the buffer is big enough to handle the address and data.
  if (buffer.size() <
      register_data.size() + static_cast<uint32_t>(register_address_size_)) {
    return pw::Status::OutOfRange();
  }

  ByteBuilder builder = ByteBuilder(buffer);
  PutRegisterAddressInByteBuilder(
      builder, register_address, order_, register_address_size_);

  switch (register_data_size) {
    case 1:
      builder.append(register_data.data(), register_data.size());
      break;

    case 2:
      PutRegisterData16InByteBuilder(builder, register_data, order_);
      break;

    case 4:
      PutRegisterData32InByteBuilder(builder, register_data, order_);
      break;

    default:
      PW_CRASH("Invalid data size being put in byte buffer");
  }

  if (!builder.ok()) {
    return pw::Status::Internal();
  }

  ConstByteSpan write_buffer(builder.data(), builder.size());
  return WriteFor(write_buffer, for_at_least);
}

Status RegisterDevice::ReadRegisters(
    uint32_t register_address,
    ByteSpan return_data,
    chrono::SystemClock::duration for_at_least) {
  ByteBuffer<sizeof(register_address)> byte_buffer;

  PutRegisterAddressInByteBuilder(
      byte_buffer, register_address, order_, register_address_size_);

  if (!byte_buffer.ok()) {
    return pw::Status::Internal();
  }

  return WriteReadFor(byte_buffer.data(),
                      byte_buffer.size(),
                      return_data.data(),
                      return_data.size(),
                      for_at_least);
}

}  // namespace i2c
}  // namespace pw
