// Copyright (c) 2026 - 2026 kio@little-bat.de
// BSD-2-Clause license
// https://opensource.org/licenses/BSD-2-Clause

#pragma once
#include "Graphics/CharMap.h"
#include "Graphics/Color.h"
#include "VideoPlane.h"


namespace kilipili::Video
{
using Color			= Graphics::Color;
using CharMap		= Graphics::CharMap;
using CharMap_wAttr = Graphics::CharMap_wAttr;


/*	The CharacterFrameBuffer is the bare minimum character-based FrameBuffer:
	It supports only one foreground and one background color. No attributes!
	Inverted colors (or bold characters) may be achieved with bit:7 by replacing character codes 128++.

	Characters are expected to be 8 pixels wide and 12 pixels high.
	All character codes incl. 0x00 are available.
*/
template<bool small = false>
class CharacterFrameBuffer : public VideoPlane
{
	CharacterFrameBuffer(const CharMap& charmap, uchar* font, Color fg, Color bg) noexcept;
	NO_COPY_MOVE(CharacterFrameBuffer);

	void setColors(Color fg, Color bg) noexcept;

	void vblank() noexcept override;
	void renderScanline(int row, int width, uint32* buffer) noexcept override;

	static constexpr int char_width	 = 8;
	static constexpr int char_height = 12;

	cptr   screen;
	int	   rows, cols;
	uchar* font;

	using ColorStrip = Color[small ? 4 : 8];
	ColorStrip __aligned(4) colorstrips[small ? 16 : 256]; // 128 or 4k colors

	cptr row_ptr;	  // character row
	int	 raster_line; // line within character
	int	 last_y;
};


/*	template class CharacterFrameBuffer uses one attribute per character.
	The attribute immediately follows it's respective character code.
	=> In LE the character code is in the low byte, the attribute in the high byte.
	The attributes are configurable per template arguments:
	Attributes are byte-size => the total number of attribute bits must not exceed 8.
	template parameters:
		fgbits: foreground color bits: 0 .. 8
		bgbits: background color bits: 0 .. 8
		bold:   enable bold attribute
*/

template<int fg_bits, int bg_bits, bool bold = true, bool underline = true>
class CharacterFrameBuffer_wAttr : public VideoPlane
{
	static_assert(fg_bits + bg_bits + bold + underline <= 8);
	static_assert(uint(fg_bits <= 8));
	static_assert(uint(bg_bits <= 8));

public:
	CharacterFrameBuffer_wAttr(const CharMap_wAttr&, uchar* font, const Color* fg, const Color* bg) noexcept;
	NO_COPY_MOVE(CharacterFrameBuffer_wAttr);

	void vblank() noexcept override;
	void renderScanline(int row, int width, uint32* buffer) noexcept override;

	static constexpr int   fg_ss		  = 0;
	static constexpr int   bg_ss		  = fg_bits;
	static constexpr uchar fg_mask		  = ((1 << fg_bits) - 1) << fg_ss;
	static constexpr uchar bg_mask		  = ((1 << bg_bits) - 1) << bg_ss;
	static constexpr uchar bold_mask	  = bold << (fg_bits + bg_bits);
	static constexpr uchar underline_mask = underline << (fg_bits + bg_bits + bold);

	static constexpr int char_width	 = 8;
	static constexpr int char_height = 12;

	uchar* screen;
	int	   rows, cols;
	uchar* font;

	const Color* fgcolors;
	const Color* bgcolors;

	const uchar* row_ptr;	  // character row
	int			 raster_line; // line within character
	int			 last_y;
};


} // namespace kilipili::Video


/*





































*/
