// 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_hdlc/encoder.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstring>
#include <span>

#include "pw_bytes/endian.h"
#include "pw_hdlc/internal/encoder.h"
#include "pw_varint/varint.h"

using std::byte;

namespace pw::hdlc {
namespace internal {

Status EscapeAndWrite(const byte b, stream::Writer& writer) {
  if (b == kFlag) {
    return writer.Write(kEscapedFlag);
  }
  if (b == kEscape) {
    return writer.Write(kEscapedEscape);
  }
  return writer.Write(b);
}

Status Encoder::WriteData(ConstByteSpan data) {
  auto begin = data.begin();
  while (true) {
    auto end = std::find_if(begin, data.end(), NeedsEscaping);

    if (Status status = writer_.Write(std::span(begin, end)); !status.ok()) {
      return status;
    }
    if (end == data.end()) {
      fcs_.Update(data);
      return OkStatus();
    }
    if (Status status = EscapeAndWrite(*end, writer_); !status.ok()) {
      return status;
    }
    begin = end + 1;
  }
}

Status Encoder::FinishFrame() {
  if (Status status =
          WriteData(bytes::CopyInOrder(std::endian::little, fcs_.value()));
      !status.ok()) {
    return status;
  }
  return writer_.Write(kFlag);
}

size_t Encoder::MaxEncodedSize(uint64_t address, ConstByteSpan payload) {
  constexpr size_t kFcsMaxSize = 8;  // Worst case FCS: 0x7e7e7e7e.
  size_t max_encoded_address_size = varint::EncodedSize(address) * 2;
  size_t encoded_payload_size =
      payload.size() +
      std::count_if(payload.begin(), payload.end(), NeedsEscaping);

  return max_encoded_address_size + sizeof(kUnusedControl) +
         encoded_payload_size + kFcsMaxSize;
}

Status Encoder::StartFrame(uint64_t address, std::byte control) {
  fcs_.clear();
  if (Status status = writer_.Write(kFlag); !status.ok()) {
    return status;
  }

  std::array<std::byte, 16> metadata_buffer;
  size_t metadata_size =
      varint::Encode(address, metadata_buffer, kAddressFormat);
  if (metadata_size == 0) {
    return Status::InvalidArgument();
  }

  metadata_buffer[metadata_size++] = control;
  return WriteData(std::span(metadata_buffer).first(metadata_size));
}

}  // namespace internal

Status WriteUIFrame(uint64_t address,
                    ConstByteSpan payload,
                    stream::Writer& writer) {
  if (internal::Encoder::MaxEncodedSize(address, payload) >
      writer.ConservativeWriteLimit()) {
    return Status::ResourceExhausted();
  }

  internal::Encoder encoder(writer);

  if (Status status = encoder.StartUnnumberedFrame(address); !status.ok()) {
    return status;
  }
  if (Status status = encoder.WriteData(payload); !status.ok()) {
    return status;
  }
  return encoder.FinishFrame();
}

}  // namespace pw::hdlc
