#ifndef BUFFER_HPP
#define BUFFER_HPP

#include <algorithm>
#include <vector>
#include <string>

/*
  file format:
   |block1|block2|...|blockN|
  block format:
   |block_size|buffer_contents|
  buffer format is:
   |frame1|frame2|...|frameN|
  frame format is:
   |entry_count|entry1|entry2|...|entryN|
 */


namespace prof {

  class Frame;

  class Buffer
  {
  public:
    typedef std::vector<unsigned long> LongVec;

    Buffer(unsigned int buff_size, unsigned int high_water_mark,
	   const std::string& filename);
    ~Buffer();

    int slotsLeft() const { return std::distance(pos_,end_); }
    int slotsUsed() const { return std::distance(beg_,pos_); }
    void checkSpace();

  private:
    Buffer(const Buffer&) { }
    Buffer& operator=(const Buffer&) { return *this; }

    friend class Frame;

    void writeBuffer();
    void clearBuffer();

    std::string filename_;
    int fd_;
    unsigned int buff_size_; // should be set by environment variable
    unsigned int high_water_;
    LongVec buff_;
    LongVec::iterator beg_;
    LongVec::iterator pos_;
    LongVec::iterator end_;
  };

  class Frame
  {
  public:
    ~Frame();
    explicit Frame(Buffer& imp);

    void add(unsigned long item);
    int total() const;

  private:
    Frame(const Frame& other):imp_(other.imp_) { }
    Frame& operator=(const Frame& other) { return *this; }

    Buffer& imp_;
    unsigned int maxadds_;
    Buffer::LongVec::iterator pos_;
  };
}
#endif
