// 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.
#pragma once

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstring>
#include <functional>  // std::invoke

#include "pw_assert/assert.h"
#include "pw_bytes/span.h"
#include "pw_checksum/crc32.h"
#include "pw_hdlc/internal/protocol.h"
#include "pw_result/result.h"
#include "pw_status/status.h"

namespace pw::hdlc {

// Represents the contents of an HDLC frame -- the unescaped data between two
// flag bytes. Instances of Frame are only created when a full, valid frame has
// been read.
class Frame {
 public:
  // The minimum size of a frame, excluding control bytes (flag or escape).
  static constexpr size_t kMinContentSizeBytes =
      kMinAddressSize + kControlSize + kFcsSize;

  static Result<Frame> Parse(ConstByteSpan frame);

  constexpr uint64_t address() const { return address_; }

  constexpr std::byte control() const { return control_; }

  constexpr ConstByteSpan data() const { return data_; }

 private:
  // Creates a Frame with the specified data. The data MUST be valid frame data
  // with a verified frame check sequence.
  constexpr Frame(uint64_t address, std::byte control, ConstByteSpan data)
      : data_(data), address_(address), control_(control) {}

  ConstByteSpan data_;
  uint64_t address_;
  std::byte control_;
};

// The Decoder class facilitates decoding of data frames using the HDLC
// protocol, by returning packets as they are decoded and storing incomplete
// data frames in a buffer.
//
// The Decoder class does not own the buffer it writes to. It can be used to
// write bytes to any buffer. The DecoderBuffer template class, defined below,
// allocates a buffer.
class Decoder {
 public:
  constexpr Decoder(ByteSpan buffer)
      : buffer_(buffer),
        last_read_bytes_({}),
        last_read_bytes_index_(0),
        current_frame_size_(0),
        state_(State::kInterFrame) {}

  Decoder(const Decoder&) = delete;
  Decoder& operator=(const Decoder&) = delete;
  Decoder(Decoder&&) = default;
  Decoder& operator=(Decoder&&) = default;

  /// @brief Parses a single byte of an HDLC stream.
  ///
  /// @returns @rst
  /// A ``pw::Result`` with the complete frame if the byte completes a
  /// frame. The status can be one of the following:
  ///
  /// .. pw-status-codes::
  ///
  ///    OK: A frame was successfully decoded. The ``Result`` contains
  ///    the ``Frame``, which is invalidated by the next ``Process()`` call.
  ///
  ///    UNAVAILABLE: No frame is available.
  ///
  ///    RESOURCE_EXHAUSTED: A frame completed, but it was too large
  ///    to fit in the decoder's buffer.
  ///
  ///    DATA_LOSS: A frame completed, but it was invalid. The frame
  ///    was incomplete or the frame check sequence verification failed.
  ///
  /// @endrst
  Result<Frame> Process(std::byte new_byte);

  // Returns the buffer space required for a `Decoder` to successfully decode a
  // frame whose on-the-wire HDLC encoded size does not exceed `max_frame_size`.
  static constexpr size_t RequiredBufferSizeForFrameSize(
      size_t max_frame_size) {
    // Flag bytes aren't stored in the internal buffer, so we can save a couple
    // bytes.
    return max_frame_size < Frame::kMinContentSizeBytes
               ? Frame::kMinContentSizeBytes
               : max_frame_size - 2;
  }

  /// @brief Processes a span of data and calls the provided callback with each
  /// frame or error.
  template <typename F, typename... Args>
  void Process(ConstByteSpan data, F&& callback, Args&&... args) {
    for (std::byte b : data) {
      auto result = Process(b);
      if (result.status() != Status::Unavailable()) {
        callback(std::forward<Args>(args)..., result);
      }
    }
  }

  // Returns the maximum size of the Decoder's frame buffer.
  size_t max_size() const { return buffer_.size(); }

  // Clears and resets the decoder.
  void Clear() {
    state_ = State::kInterFrame;
    Reset();
  }

 private:
  // State enum class is used to make the Decoder a finite state machine.
  enum class State {
    kInterFrame,
    kFrame,
    kFrameEscape,
  };

  void Reset() {
    current_frame_size_ = 0;
    last_read_bytes_index_ = 0;
    fcs_.clear();
  }

  void AppendByte(std::byte new_byte);

  Status CheckFrame() const;

  bool VerifyFrameCheckSequence() const;

  ByteSpan buffer_;

  // Ring buffer of the last four bytes read into the current frame, to allow
  // calculating the frame's CRC incrementally. As data is evicted from this
  // buffer, it is added to the running CRC. Once a frame is complete, the
  // buffer contains the frame's FCS.
  std::array<std::byte, sizeof(uint32_t)> last_read_bytes_;
  size_t last_read_bytes_index_;

  // Incremental checksum of the current frame.
  checksum::Crc32 fcs_;

  size_t current_frame_size_;

  State state_;
};

// DecoderBuffers declare a buffer along with a Decoder.
template <size_t kSizeBytes>
class DecoderBuffer : public Decoder {
 public:
  DecoderBuffer() : Decoder(frame_buffer_) {}

  /// DecoderBuffer is not movable, as the decoder stores pointers into the
  /// frame buffer.
  DecoderBuffer(DecoderBuffer&&) = delete;

  /// DecoderBuffer is not movable, as the decoder stores pointers into the
  /// frame buffer.
  DecoderBuffer& operator=(DecoderBuffer&&) = delete;

  // Returns the maximum length of the bytes that can be inserted in the bytes
  // buffer.
  static constexpr size_t max_size() { return kSizeBytes; }

 private:
  static_assert(kSizeBytes >= Frame::kMinContentSizeBytes);

  std::array<std::byte, kSizeBytes> frame_buffer_;
};

}  // namespace pw::hdlc
