#ifndef TERMINAL_PARSER_H
#define TERMINAL_PARSER_H

/****************************************************************************************************************/

#if defined(linux) || defined(WIN32)

#error TODO: Need Core4 types and atomic swap

#else

#include <core/types.h>		/* Types like uint8, uint16, ...	*/

#endif

#include <sys/cdefs.h>

__BEGIN_DECLS

/****************************************************************************************************************/
//
// This structure lists all callbacks that are called from the terminal parser
//
struct terminal_parser;
struct terminal_cell;

struct terminal_parser_operations {
  // Update character at screen position (If this function exists, cells never become dirty)
  void (*update)(struct terminal_parser *tpm, uint x, uint y, struct terminal_cell *cell);

  // Refresh screen (Need only to re-paint the dirty cells)
  void (*refresh)(struct terminal_parser *tpm);

  // Terminal response
  void (*respond)(struct terminal_parser *tpm, const void *data, size_t len);

  // Bell signal
  void (*bell)(struct terminal_parser *tpm);

  // Change state of LEDs (-1 tells driver to set leds to it's own liking, host has lost interest in them)
  void (*set_led)(struct terminal_parser *tpm, int bits);

  // Enable disable keyboard clicks
  void (*set_click)(struct terminal_parser *tpm, int volume);

  // Copy an area around. Saves updating individual cells.
  void (*scroll_up)(struct terminal_parser *tpm, uint top, uint bot);
  void (*scroll_down)(struct terminal_parser *tpm, uint top, uint bot);
};

/****************************************************************************************************************/

#define TPM_ATTR_INTENSITY		1	// Bold or high brightness
#define TPM_ATTR_DIM			2	// Lower brightness
#define TPM_ATTR_BLINK			4	// Blink this cell
#define TPM_ATTR_FAST_BLINK		8	// Faster, faster...
#define TPM_ATTR_UNDERLINE		16	// Underlined character
#define TPM_ATTR_REVERSE		32	// Swap foreground and background color
#define TPM_ATTR_ITALIC			64	// Italic text
#define TPM_ATTR_DIRTY			128	// Need repaint
// Not implemented:
#define TPM_ATTR_CONCEALED		0	// Character not visible
#define TPM_ATTR_DOUBLE_UNDERLINE	0	// Two lines below
#define TPM_ATTR_CROSSED_OUT		0	// One line through the middle
#define TPM_ATTR_FRAMED			0	// Paint a box around it
#define TPM_ATTR_ENCIRCLED		0	// A circle around it
#define TPM_ATTR_OVERLINE		0	// A line above

/****************************************************************************************************************/

#define TPM_LINE_SIZE		3		// Mask for determining character size (Only used in line attr)
#define TPM_LINE_SIZE_NORMAL	0		// Normal size
#define TPM_LINE_SIZE_WIDE	1		// Double width line
#define TPM_LINE_SIZE_TOP	2		// Top half of double height line
#define TPM_LINE_SIZE_BOT	3		// Bottom half of double height line
#define TPM_LINE_BLINK		4		// Line has blinking characters
#define TPM_LINE_DIRTY		128		// Need repaint

/****************************************************************************************************************/
//
// Holds information about a single character on screen
//
struct terminal_cell {
  union {
    struct {
      uint16 ch;		// Character code
      uint8 attr;		// Attribute flags
      uint fgidx:4;		// Foreground color index
      uint bgidx:4;		// Background color index
    };
    uint32 value;		// Alltogether
  };
};

/****************************************************************************************************************/
//
// These are the user visible parts of the terminal parser structure
//
struct terminal_parser {
  uint tpm_w;				// Screen size
  uint tpm_h;

  uint tpm_x;				// Current cursor position
  uint tpm_y;

  struct terminal_cell *tpm_screen;	// Buffers visible text

  uint8 *tpm_line_attr;			// Line attributes for each line (dirty bit, character size)

  void *tpm_user_data;

  const struct terminal_parser_operations *tpm_op;	// Callbacks

  uint tpm_leds;			// Host controlled LED state

  union {
    uint tpm_flags;			// All flags together
    struct {
      uint tpm_dirty:1;			// Flag: At least one cell is dirty
      uint tpm_lnm:1;			// Flag: Automagically insert CR before LF
      uint tpm_decawm:1;		// Flag: Auto wrap at line end
      uint tpm_revawm:1;		// Flag: Reverse auto wrap at line start
      uint tpm_kam:1;			// Flag: Keyboard active
      uint tpm_srm:1;			// Flag: Local echo if zero
      uint tpm_decckm:1;		// Flag: Cursor keys generate application codes
      uint tpm_deckpam:1;		// Flag: Keypad generates application codes
      uint tpm_decklhim:1;		// Flag: Keyboard LEDs controlled by host
      uint tpm_decarm:1;		// Flag: Auto-repeat mode
      uint tpm_irm:1;			// Flag: Insert mode if set
      uint tpm_dectcem:1;		// Flag: Cursor visible
      uint tpm_s8c1t:1;			// Flag: Send responses using 8-bit control codes
      uint tpm_utf8:1;			// Flag: Process characters as UTF8
      uint tpm_blinking:1;		// Flag: At least one character on screen is blinking
      uint tpm_blink_state:1;		// Flag: State of blinking characters
      uint tpm_fast_blink_state:1;	// Flag: State of fast blinking characters
      uint tpm_deccrtsm:1;		// Flag: Screen saver enabled
      uint tpm_decskcv:4;		// Flag: Key click volume
      uint tpm_norefresh:1;		// Flag: Do not call refresh after each write
    };
  };
  
  unsigned int tpm_default_flags;	// Flags reset to this on reset
};

/****************************************************************************************************************/
//
// Flags used with keyboard entry
//
#define TPM_KEY_REPEAT	1
#define TPM_KEY_NUM	2
#define TPM_KEY_CAPS	4

/****************************************************************************************************************/

struct terminal_parser *terminal_parser_init(uint width, uint height,
					     const struct terminal_parser_operations *op, void *user_data);
void terminal_parser_free(struct terminal_parser *tpm);

// Data that goes to screen
void terminal_parser_write(struct terminal_parser *tpm, const void *buf, size_t size);

// Data that goes to host
void terminal_parser_respond(struct terminal_parser *tpm, const void *data, size_t len);

// Cause screen update: Paint anything that has changed since last call
void terminal_parser_update(struct terminal_parser *tpm);

// Full screen redraw: Repaint the full terminal screen
void terminal_parser_redraw(struct terminal_parser *tpm);

/****************************************************************************************************************/
__END_DECLS
#endif
