#pragma once

#include <string>
#include <vector>
#include <memory>

#include <readline/LineInterface.h>
#include <alib/iterator>

namespace cli {

class CharSequence {
	std::shared_ptr < LineInterface > m_lineInterface;
	std::string putbackBuffer;

	const char * linePtr = nullptr;
	std::vector < std::string > m_lines;

	void fetch ( bool readNextLine );

	std::string getData ( ) const;

	size_t m_line = 0;
	size_t m_position = 0;
public:
	explicit CharSequence ( std::shared_ptr < cli::LineInterface > reader ) : m_lineInterface ( std::move ( reader ) ) {
	}

	template < std::derived_from < LineInterface > Interface >
	explicit CharSequence ( Interface && reader ) : m_lineInterface ( std::make_shared < Interface > ( std::forward < Interface > ( reader ) ) ) { //NOLINT(bugprone-forwarding-reference-overload)
	}

	CharSequence ( CharSequence && ) = default;

	CharSequence ( const CharSequence & ) = delete;

	CharSequence & operator = ( CharSequence && ) = delete;

	CharSequence & operator = ( const CharSequence & ) = delete;

	~CharSequence ( ) {
		if ( m_lineInterface )
			m_lineInterface->lineCallback ( getData ( ) );
	}

	int getCharacter ( ) const;

	void advance ( bool readNextLine );

	void putback ( std::string string, size_t line, size_t position ) {
		m_line = line;
		m_position = position;
		putbackBuffer.insert ( putbackBuffer.end ( ), string.rbegin ( ), string.rend ( ) );
	}

	size_t getLine ( ) const {
		return m_line;
	}

	size_t getPosition ( ) const {
		return m_position;
	}
};

} /* namespace cli */

