
#ifndef history_h_INCLUDED 
#define history_h_INCLUDED

#ifndef DISABLE_OUTPUT_HISTORY

#include "tracelog.h"
#include "config.h"
#include "types.h"
#include "z_ucs.h"

#define HISTORY_METADATA_TYPE_FONT 0
#define HISTORY_METADATA_TYPE_STYLE 1
#define HISTORY_METADATA_TYPE_COLOUR 2

struct history_metadata
{
  /*@dependent@*/ z_ucs *history_index;
  int metadata_type;
  int16_t parameter1;
  int16_t parameter2;
};

typedef struct
{
  int window_number;

  size_t z_history_maximum_buffer_size;
  size_t z_history_buffer_increment_size;
  size_t z_history_metadata_increment_size;

  // z_history_buffer is a circular array. empty in case front=NULL,
  // full in case front+1==back.
  /*@null@*/ /*@only@*/ z_ucs *z_history_buffer;
  /*@null@*/ /*@dependent@*/ z_ucs *z_history_buffer_last_element;
  // We keep two sizes for the history buffer: The raw size, and the "real"
  // size, which is equal to the raw size minus a string-terminating zero.
  size_t z_history_buffer_size;
  size_t z_history_buffer_raw_size;
  /*@null@*/ /*@dependent@*/ z_ucs *z_history_buffer_front_index;
  /*@null@*/ /*@dependent@*/ z_ucs *z_history_buffer_back_index;
  /*@null@*/ /*@only@*/ struct history_metadata *history_metadata_buffer;
  size_t history_buffer_metadata_size;
  int history_buffer_metadata_index;

  // These four values are set when fizmo opens the interface (and when the
  // values are used in the current version). They keep the current state of
  // the back-end index of the history queue. This is necessary, since
  // for example the command to set colour to a given value has already
  // been overwritten in the history, but the text using the colour is still
  // in the buffer.
  z_font history_buffer_back_index_font;
  z_style history_buffer_back_index_style;
  z_colour history_buffer_back_index_foreground;
  z_colour history_buffer_back_index_background;

  z_ucs **paragraph_pos_cache;
  int pos_cache_size;
  int pos_cache_max_paragraph;
} OUTPUTHISTORY;

struct history_repetition_target
{
  void (*set_text_style)(z_style text_style);
  void (*set_colour)(z_colour foreground, z_colour background, int16_t window);
  void (*set_font)(z_font font_type);
  void (*z_ucs_output)(z_ucs *z_ucs_output);
  void (*repeat_starts_from_buffer_begin)();
};

typedef OUTPUTHISTORY /*@null@*/ /*@only@*/ *outputhistory_ptr;

#ifndef history_c_INCLUDED
extern outputhistory_ptr outputhistory[];
#endif

OUTPUTHISTORY *create_outputhistory(int window_number,
    size_t maximum_buffer_size, size_t buffer_increment_size,
    size_t metadata_increment_size, z_colour foreground_colour,
    z_colour background_color, z_font font, z_style style);

void destroy_outputhistory(/*@only@*/ OUTPUTHISTORY *history);

void store_z_ucs_output_in_history(OUTPUTHISTORY *history,
    z_ucs *z_ucs_output);

void store_metadata_in_history(OUTPUTHISTORY *history, int metadata_type,
    int16_t parameter1, int16_t parameter2);

void repeat_paragraphs_from_history(OUTPUTHISTORY *history,
    int start_paragraph_number, int end_paragraph_number,
    bool allow_adjust_start_paragraph,
    struct history_repetition_target *target);

int get_paragraph_y_positions(OUTPUTHISTORY *history, int screen_width,
    int bottom_y, int *bottom_y_pos, int top_y, int *top_y_pos,
    int left_padding);

// Used to remove preloaded input:
void remove_chars_from_history(OUTPUTHISTORY *history, int nof_chars);

/*@null@*/ z_ucs *get_current_line(/*@null@*/ OUTPUTHISTORY *history);


#endif // DISABLE_OUTPUT_HISTORY

#endif /* history_h_INCLUDED */

