#ifndef ARCANE__TERM_H
#define ARCANE__TERM_H

/*
 * arcane - A rogue-like game engine
 * Copyright (C) 2005  Petr Baudis <pasky@ucw.cz>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <string>

// XXX: This should be generic if we ever get more terminal backends.
#include "uti/termenum.h"


typedef enum uti_keys Key;

enum Color {
	COLOR_ANY = -1,

	COLOR_BLACK = 0,
	COLOR_RED,
	COLOR_GREEN,
	COLOR_BROWN,
	COLOR_BLUE,
	COLOR_MAGENTA,
	COLOR_CYAN,
	COLOR_GRAY,

	COLOR_DARKGRAY,
	COLOR_LIGHTRED,
	COLOR_LIGHTGREEN,
	COLOR_YELLOW,
	COLOR_LIGHTBLUE,
	COLOR_PINK,
	COLOR_LIGHTCYAN,
	COLOR_WHITE
};


class Term {
public:
	Term();
	virtual ~Term();

	/* You can do stuff like:
	 *
	 *	term->cursor(1, 2).color(COLOR_YELLOW).put("xyzzy");
	 *
	 * to put a character of given color at the given position, or:
	 *
	 *	term << "xyzzy" << "foo";
	 *
	 * Of course you could do even something like:
	 *
	 * 	(term << "bar").cursor(2, 3) << "baz";
	 *
	 * but the readibility is not high. */

	/* OTOH you can also do:
	 *
	 *	char ch;
	 *	term >> ch;
	 *
	 * or also:
	 *
	 *	std::string str;
	 *	term >> str;
	 *
	 * However the value of such an expression is char or std::string
	 * reference, *NOT* Term.
	 *
	 * Alternatively, there is a get() method, with the same semantics
	 * as the >> operator. */

	virtual Term &color(enum Color fg, enum Color bg = COLOR_ANY) = 0;
	virtual Term &cursor(int x, int y) = 0;

	virtual Term &put(const std::string str) = 0;
	Term &put(char ch);
	Term &put(long num, int width = 0);
	Term &put(unsigned long num, int width = 0);
	Term &put(int num, int width = 0);
	virtual Term &clear(int x1, int y1, int x2, int y2) = 0;

	virtual Key &get(Key &ch) = 0;
	std::string &get(std::string &str);
	int &get(long &num);
	int &get(unsigned long &num);
	int &get(int &num);
	bool &get(bool &b);

	virtual void input_location(int x, int y);

	virtual int width() = 0;
	virtual int height() = 0;

protected:
	enum Color fg, bg;
	int il_x, il_y;

	virtual void backspace() = 0;
};

inline Term &
operator <<(Term &term, const std::string str)
	{ return term.put(str); }

inline Term &
operator <<(Term &term, char ch)
	{ return term.put(ch); }

inline Term &
operator <<(Term &term, long num)
	{ return term.put(num); }
inline Term &
operator <<(Term &term, unsigned long num)
	{ return term.put(num); }
inline Term &
operator <<(Term &term, int num)
	{ return term.put(num); }

inline Key &
operator >>(Term &term, Key &ch)
	{ return term.get(ch); }

inline std::string &
operator >>(Term &term, std::string &str)
	{ return term.get(str); }

inline int &
operator >>(Term &term, long &num)
	{ return term.get(num); }
inline int &
operator >>(Term &term, unsigned long &num)
	{ return term.get(num); }
inline int &
operator >>(Term &term, int &num)
	{ return term.get(num); }

inline bool &
operator >>(Term &term, bool &b)
	{ return term.get(b); }


inline
Term::Term()
	: fg(COLOR_GRAY), bg(COLOR_BLACK), il_x(0), il_y(0)
{
}

inline
Term::~Term()
{
}

inline void
Term::input_location(int x, int y)
{
	il_x = x; il_y = y;
}


#endif
