/*! \file piscreentypes.h
 * \brief Types for PIScreen
*/
/*
	PIP - Platform Independent Primitives
	Types for PIScreen
	Ivan Pelipenko peri4ko@yandex.ru

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PISCREENTYPES_H
#define PISCREENTYPES_H

#include "pip_console_export.h"
#include "pivariant.h"
#include "pivariantsimple.h"

class PIScreenTile;

namespace PIScreenTypes {
	
	//! Color for chars or background
	enum Color {
		Default /** Default */,
		Black /** Black */,
		Red /** Red */,
		Green /** Green */,
		Blue /** Blue */,
		Cyan /** Cyan */,
		Magenta /** Magenta */,
		Yellow /** Yellow */,
		White /** White */,
		Transparent /** Save previous color */
	};
	
	//! Flags for chars
	enum CharFlag {
		Bold /** Bold or bright */ = 0x1,
		Blink /** Blink text */ = 0x2,
		Underline /** Underline text */ = 0x4,
		Inverse = 0x08
	};
	
	//! Alignment
	enum Alignment {
		Left /** Left */ ,
		Center /** Center */ ,
		Right /** Right */
	};
	
	//! Size policy
	enum SizePolicy {
		Fixed /** Fixed size */ ,
		Preferred /** Preferred size */ ,
		Expanding /** Maximum available size */ ,
		Ignore /** Ignore layout logic */
	};
	
	//! Direction
	enum Direction {
		Horizontal /** Horizontal */ ,
		Vertical /** Vertical */
	};

	//! Focus flags
	enum FocusFlag {
		CanHasFocus /** Tile can has focus */ = 0x1,
		NextByTab /** Focus passed to next tile by tab key */ = 0x2,
		NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4,
		NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8,
		NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical,
		FocusOnMouse /** Tile focused on mouse press */ = 0x10,
		FocusOnWheel /** Tile focused on wheel */ = 0x20,
		FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel
	};
	
	typedef PIFlags<CharFlag> CharFlags;
	typedef PIFlags<FocusFlag> FocusFlags;
	
	union PIP_CONSOLE_EXPORT CellFormat {
		CellFormat(ushort f = 0) {raw_format = f;}
		CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
			color_char = col_char;
			color_back = col_back;
			flags = flags_;
		}
		ushort raw_format;
		struct {
			ushort color_char : 4;
			ushort color_back : 4;
			ushort flags : 8;
		};
		bool operator ==(const CellFormat & c) const {return raw_format == c.raw_format;}
		bool operator !=(const CellFormat & c) const {return raw_format != c.raw_format;}
	};
	
	struct PIP_CONSOLE_EXPORT Cell {
		Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;}
		CellFormat format;
		PIChar symbol;
		bool operator ==(const Cell & c) const {return format == c.format && symbol == c.symbol;}
		bool operator !=(const Cell & c) const {return format != c.format || symbol != c.symbol;}
		Cell & operator =(const Cell & c) {
			symbol = c.symbol;
			if (c.format.color_back == Transparent) {
				format.color_char = c.format.color_char;
				format.flags = c.format.flags;
			} else format = c.format;
			return *this;
		}
	};

	struct PIP_CONSOLE_EXPORT TileEvent {
		TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
		int type;
		PIVariant data;
	};
	
	class PIP_CONSOLE_EXPORT PIScreenBase {
	public:
		PIScreenBase() {}
		virtual ~PIScreenBase() {}
		virtual void tileEventInternal(PIScreenTile * , TileEvent) {}
		virtual void tileRemovedInternal(PIScreenTile * ) {}
		virtual void tileSetFocusInternal(PIScreenTile * ) {}
	};

}


inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}

inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::TileEvent & v) {s << v.type << v.data; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::TileEvent & v) {s >> v.type >> v.data; return s;}

REGISTER_PIVARIANTSIMPLE(PIScreenTypes::TileEvent)

#endif // PISCREENTYPES_H
