// Copyright 2020 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_hex_dump/hex_dump.h"

#include <cctype>
#include <cstddef>
#include <string_view>

#include "pw_status/status_with_size.h"
#include "pw_string/string_builder.h"
#include "pw_string/type_to_string.h"

using pw::string::HexDigitCount;
using pw::string::IntToHexString;

namespace pw::dump {
namespace {

constexpr const std::string_view kAddressSeparator(": ");
constexpr const std::string_view kSectionSeparator("  ");
constexpr const std::string_view kAddressHeader("Address");
constexpr const std::string_view kOffsetHeader("Offs.");
constexpr const std::string_view kAsciiHeader("Text");

// Minimum number of hex characters to use when displaying dump offset.
constexpr const size_t kMinOffsetChars = 4;

char PrintableChar(std::byte b) {
  if (std::isprint(std::to_integer<char>(b)) == 0) {
    return '.';
  }
  return std::to_integer<char>(b);
}

void AddGroupingByte(size_t byte_index,
                     FormattedHexDumper::Flags& flags,
                     StringBuilder& builder) {
  // Never add grouping when it is disabled.
  if (flags.group_every == 0) {
    return;
  }
  // If this byte isn't at the end of a group, don't add a space.
  if ((byte_index + 1) % flags.group_every != 0) {
    return;
  }
  // If this byte is the last byte in a line, don't add a grouping byte
  // (prevents trailing spaces).
  if (byte_index + 1 == flags.bytes_per_line) {
    return;
  }

  builder << ' ';
}

}  // namespace

Status DumpAddr(std::span<char> dest, uintptr_t addr) {
  if (dest.data() == nullptr) {
    return Status::InvalidArgument();
  }
  // Include null terminator.
  if (dest.size() < kHexAddrStringSize + 1) {
    return Status::ResourceExhausted();
  }
  dest[0] = '0';
  dest[1] = 'x';

  return IntToHexString(addr, dest.subspan(2), sizeof(uintptr_t) * 2).status();
}

Status FormattedHexDumper::PrintFormatHeader() {
  StringBuilder builder(dest_);

  if (flags.prefix_mode != AddressMode::kDisabled) {
    std::string_view header(flags.prefix_mode == AddressMode::kOffset
                                ? kOffsetHeader
                                : kAddressHeader);
    // Pad to align to address width.
    size_t padding = 0;
    if (flags.prefix_mode == AddressMode::kOffset) {
      size_t offs_width =
          HexDigitCount(source_data_.size_bytes() + current_offset_);
      padding = std::max(offs_width, kMinOffsetChars);
    } else {
      padding = kHexAddrStringSize;
    }

    padding += kAddressSeparator.length();
    padding -= header.size();

    builder << header;
    builder.append(padding, ' ');
  }

  // Print offsets.
  for (size_t i = 0; i < static_cast<size_t>(flags.bytes_per_line); ++i) {
    // Early loop termination for when bytes_remaining <
    // bytes_per_line.
    if (flags.group_every != 0 &&
        i % static_cast<uint8_t>(flags.group_every) == 0) {
      uint8_t c = static_cast<uint8_t>(i);
      if (c >> 4 == 0) {
        builder << ' ';
      } else {
        builder << std::byte(c >> 4);
      }
      builder << std::byte(c & 0xF);
    } else {
      builder.append(2, ' ');
    }
    AddGroupingByte(i, flags, builder);
  }

  if (flags.show_ascii) {
    builder << kSectionSeparator;
    builder << kAsciiHeader;
  }

  return builder.status();
}

Status FormattedHexDumper::DumpLine() {
  if (source_data_.empty()) {
    return Status::ResourceExhausted();
  }

  if (!ValidateBufferSize().ok() || dest_.data() == nullptr) {
    return Status::FailedPrecondition();
  }

  if (dest_[0] == 0 && flags.show_header) {
    // First line, print out dump format header.
    return PrintFormatHeader();
  }

  StringBuilder builder(dest_);
  // Dump address/offset prefix.
  // TODO(amontanez): This block can be much nicer if StringBuilder exposed an
  // easy way to control zero padding for hex address.
  if (flags.prefix_mode != AddressMode::kDisabled) {
    uintptr_t val;
    if (flags.prefix_mode == AddressMode::kAbsolute) {
      val = reinterpret_cast<uintptr_t>(source_data_.data());
      builder << "0x";
      uint8_t significant = HexDigitCount(val);
      builder.append(sizeof(uintptr_t) * 2 - significant, '0');
    } else {
      val = current_offset_;
      size_t significant =
          HexDigitCount(source_data_.size_bytes() + current_offset_);
      if (significant < kMinOffsetChars) {
        builder.append(kMinOffsetChars - significant, '0');
      }
    }
    if (val != 0) {
      builder << reinterpret_cast<void*>(val);
    } else {
      builder.append(2, '0');
    }
    builder << kAddressSeparator;
  }

  size_t bytes_in_line = std::min(source_data_.size_bytes(),
                                  static_cast<size_t>(flags.bytes_per_line));
  // Convert raw bytes to hex characters.
  for (size_t i = 0; i < bytes_in_line; ++i) {
    // Early loop termination for when bytes_remaining <
    // bytes_per_line.
    uint8_t c = std::to_integer<uint8_t>(source_data_[i]);
    // TODO(amontanez): Maybe StringBuilder can be augmented to support full-
    // width bytes? (`04` instead of `4`, for example)
    builder << std::byte(c >> 4);
    builder << std::byte(c & 0xF);
    AddGroupingByte(i, flags, builder);
  }
  // Add padding spaces to ensure lines are aligned.
  if (flags.show_ascii) {
    for (size_t i = bytes_in_line;
         i < static_cast<size_t>(flags.bytes_per_line);
         ++i) {
      builder.append(2, ' ');
      AddGroupingByte(i, flags, builder);
    }
  }

  // Interpret bytes as characters.
  if (flags.show_ascii) {
    builder << kSectionSeparator;
    for (size_t i = 0; i < bytes_in_line; ++i) {
      builder << PrintableChar(source_data_[i]);
    }
  }

  source_data_ = source_data_.subspan(bytes_in_line);
  current_offset_ += bytes_in_line;
  return builder.status();
}

Status FormattedHexDumper::SetLineBuffer(std::span<char> dest) {
  if (dest.data() == nullptr || dest.size_bytes() == 0) {
    return Status::InvalidArgument();
  }
  dest_ = dest;
  return ValidateBufferSize().ok() ? OkStatus() : Status::ResourceExhausted();
}

Status FormattedHexDumper::BeginDump(ConstByteSpan data) {
  current_offset_ = 0;
  source_data_ = data;
  if (data.data() == nullptr) {
    return Status::InvalidArgument();
  }
  if (dest_.data() != nullptr && dest_.size_bytes() > 0) {
    dest_[0] = 0;
  }
  return ValidateBufferSize().ok() ? OkStatus() : Status::FailedPrecondition();
}

Status FormattedHexDumper::ValidateBufferSize() {
  // Minimum size is number of bytes per line as hex pairs plus the null
  // terminator.
  size_t required_size = flags.bytes_per_line * 2 + 1;
  if (flags.show_ascii) {
    required_size += kSectionSeparator.length() + flags.bytes_per_line;
  }
  if (flags.prefix_mode == AddressMode::kAbsolute) {
    required_size += kHexAddrStringSize;
    required_size += kAddressSeparator.length();
  } else if (flags.prefix_mode == AddressMode::kOffset) {
    required_size +=
        HexDigitCount(std::max(source_data_.size_bytes(), kMinOffsetChars));
    required_size += kAddressSeparator.length();
  }
  if (flags.group_every != 0) {
    required_size += (flags.bytes_per_line - 1) / flags.group_every;
  }

  if (dest_.size_bytes() < required_size) {
    return Status::ResourceExhausted();
  }

  return OkStatus();
}

}  // namespace pw::dump
