// 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_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.
//
// For now, the Frame class assumes a single-byte control field and a 32-bit
// frame check sequence (FCS).
class Frame {
 private:
  static constexpr size_t kMinimumAddressSize = 1;
  static constexpr size_t kControlSize = 1;
  static constexpr size_t kFcsSize = sizeof(uint32_t);

 public:
  // The minimum size of a frame, excluding control bytes (flag or escape).
  static constexpr size_t kMinSizeBytes =
      kMinimumAddressSize + 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;

  // Parses a single byte of an HDLC stream. Returns a Result with the complete
  // frame if the byte completes a frame. The status is the following:
  //
  //     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.
  //
  Result<Frame> Process(std::byte new_byte);

  // 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()) {
        std::invoke(
            std::forward<F>(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;

  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_) {}

  // 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::kMinSizeBytes);

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

}  // namespace pw::hdlc
