// 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 timeout) {
  // 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,
                                  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, data_order_);
      break;

    case 4:
      PutRegisterData32InByteBuilder(builder, register_data, data_order_)
          .IgnoreError();  // TODO(pwbug/387): Handle Status properly
      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, timeout);
}

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

  PutRegisterAddressInByteBuilder(byte_buffer,
                                  register_address,
                                  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(),
                      timeout);
}

}  // namespace i2c
}  // namespace pw
