#ifndef ORIGINCAR_BASE__SERIAL_FRAME_PARSER_HPP_
#define ORIGINCAR_BASE__SERIAL_FRAME_PARSER_HPP_

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <vector>

namespace origincar_base_core
{

class SerialFrameParser
{
public:
  static constexpr std::size_t kFrameSize = 24;

  static constexpr uint8_t frameHeader() {return 0x7B;}
  static constexpr uint8_t frameTail() {return 0x7D;}

  void append(const uint8_t * data, std::size_t size)
  {
    buffer_.insert(buffer_.end(), data, data + size);
  }

  bool popFrame(std::array<uint8_t, kFrameSize> * frame)
  {
    while (!buffer_.empty()) {
      const auto header = std::find(buffer_.begin(), buffer_.end(), frameHeader());
      if (header == buffer_.end()) {
        buffer_.clear();
        return false;
      }
      buffer_.erase(buffer_.begin(), header);
      if (buffer_.size() < kFrameSize) {
        return false;
      }
      if (buffer_[kFrameSize - 1] != frameTail()) {
        buffer_.erase(buffer_.begin());
        continue;
      }

      std::copy_n(buffer_.begin(), kFrameSize, frame->begin());
      buffer_.erase(buffer_.begin(), buffer_.begin() + kFrameSize);
      return true;
    }
    return false;
  }

private:
  std::vector<uint8_t> buffer_;
};

}  // namespace origincar_base_core

#endif  // ORIGINCAR_BASE__SERIAL_FRAME_PARSER_HPP_
