#ifndef INCLUDED_BOBCAT_READLINEHISTORY_
#define INCLUDED_BOBCAT_READLINEHISTORY_

#include <iterator>
#include <string>
#include <vector>

#include <readline/history.h>

namespace FBB
{

struct ReadLineHistory
{
    friend std::ostream &operator<<(std::ostream &out,
                                    ReadLineHistory const &history);
    friend std::istream &operator>>(std::istream &out,
                                    ReadLineHistory &history);

    class HistoryElement                // stores the pointers to the 
    {                                   // relevant elements in HIST_ENTRY
        friend struct ReadLineHistory;  // elements

        char const *d_line;     
        char const *d_timestamp;

        public:
            char const *line() const;                                   // .f
            char const *timestamp() const;                              // .f

        private:
            HistoryElement() = default;

            HistoryElement &operator=(HIST_ENTRY const *element);
    };

    using ElementsPtr = HistoryElement *;
    using ElementsConstPtr = HistoryElement const *;

    struct const_iterator
    {
        using iterator_category = std::input_iterator_tag;
        using difference_type   = std::ptrdiff_t;
        using value_type        = HistoryElement const;
        using pointer           = value_type *;
        using reference         = value_type &;

        private:
            friend ReadLineHistory;
            friend std::reverse_iterator<const_iterator>;

            size_t d_idx;               // idx of a history element

            ElementsConstPtr d_elements;

        public:
            const_iterator &operator++();                               // .f
            const_iterator operator++(int);                             // .f
            bool operator==(const_iterator const &rhs) const;           // .f
            bool operator!=(const_iterator const &rhs) const;           // .f
            HistoryElement const &operator*() const;
            HistoryElement const *operator->() const;                   // .f

        private:
            const_iterator(HistoryElement const *vect); // last element    .f
            const_iterator(HistoryElement const *vect, size_t idx);     // .f

                                            // for the reverse iter.
            const_iterator &operator--();                               // .f
            const_iterator operator--(int);                             // .f
    };

    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    private:
        bool d_timestamps;              // store time stamps or not
        ElementsPtr d_elements;         // ptr to the HistoryElements

                                        // singleton
        static ReadLineHistory *s_readLineHistory;       
            
    public:
        ReadLineHistory(ReadLineHistory const &other)           = delete;
        ~ReadLineHistory();

        static ReadLineHistory &instance(bool useTimestamps = false);

        const_iterator begin() const;       // begin of the history    .f
        const_iterator end() const;         // end of the history      .f
        const_reverse_iterator rbegin() const;                      // .f
        const_reverse_iterator rend() const;                        // .f

                                            // write/read the timestamps at
                                            // insertions/extractions
        ReadLineHistory &setTimestampsIO(bool useTimestamps);       // .f

        size_t size() const;                                        // .f
        size_t maxSize() const;                                     // .f
        bool timestamps() const;                                    // .f


    private:
        ReadLineHistory();

        void destroy();

        std::istream &extract(std::istream &in);
        void setElements();

        static void insertHistoryElement(HistoryElement const &he,
                                         std::ostream &out);
        static void insertLine(HistoryElement const &he, std::ostream &out);

static std::istream &extractTimestamps(std::istream &in);
        static std::istream &extractLines(std::istream &in);
};

#include "readlinehistory.f"

} // FBB
#endif
