
#include <iostream>
#include <stdarg.h>
#include <stdlib.h>

#include "Interpreter.h"
#include "ScreenInterface.h"
#include "../c/screen_interface.h"


namespace c_fizmo
{
  extern "C" void fizmo_register_screen_interface(
      struct z_screen_interface *screen_interface);
  extern "C" void fizmo_start(char* z_story_filename,
      char *blorb_filename, char *restore_on_start_filename);
  extern "C" void fizmo_new_screen_size(int width, int height);
  extern "C" zscii unicode_char_to_zscii_input_char(z_ucs unicode_char);
  extern "C" int streams_z_ucs_output(z_ucs *z_ucs_output);
  extern "C" int streams_latin1_output(char *latin1_output);
  extern "C" size_t _i18n_va_translate(int string_code, va_list ap);
}


ScreenInterface *Interpreter::active_cpp_screen_interface;

char *cpp_get_interface_name()
{ return Interpreter::active_cpp_screen_interface->get_interface_name(); }

bool cpp_is_status_line_available()
{ return Interpreter::active_cpp_screen_interface->is_status_line_available()
  == true ? true : false; }

bool cpp_is_split_screen_available()
{ return Interpreter::active_cpp_screen_interface->is_split_screen_available()
  == true ? true : false; }

bool cpp_is_variable_pitch_font_default()
{ return Interpreter::active_cpp_screen_interface->is_variable_pitch_font_default()
  == true ? true : false; }

bool cpp_is_color_available()
{ return Interpreter::active_cpp_screen_interface->is_color_available()
  == true ? true : false; }

bool cpp_is_picture_displaying_available()
{ return Interpreter::active_cpp_screen_interface->is_picture_displaying_available()
  == true ? true : false; }

bool cpp_is_bold_face_available()
{ return Interpreter::active_cpp_screen_interface->is_bold_face_available()
  == true ? true : false; }

bool cpp_is_italic_available()
{ return Interpreter::active_cpp_screen_interface->is_italic_available()
  == true ? true : false; }

bool cpp_is_fixed_space_font_available()
{ return Interpreter::active_cpp_screen_interface->is_fixed_space_font_available()
  == true ? true : false; }

bool cpp_is_timed_keyboard_available()
{ return Interpreter::active_cpp_screen_interface->is_timed_keyboard_available()
  == true ? true : false; }

bool cpp_is_preloaded_input_available()
{ return Interpreter::active_cpp_screen_interface->is_preloaded_input_available()
  == true ? true : false; }

bool cpp_is_character_graphics_font_availiable()
{ return Interpreter::active_cpp_screen_interface->is_character_graphics_font_availiable()
  == true ? true : false; }

bool cpp_is_picture_font_availiable()
{ return Interpreter::active_cpp_screen_interface->is_picture_font_availiable()
  == true ? true : false; }

uint8_t cpp_get_screen_height()
{ return Interpreter::active_cpp_screen_interface->get_screen_height(); }

uint8_t cpp_get_screen_width()
{ return Interpreter::active_cpp_screen_interface->get_screen_width(); }

uint8_t cpp_get_screen_width_in_units()
{ return Interpreter::active_cpp_screen_interface->get_screen_width_in_units(); }

uint8_t cpp_get_screen_height_in_units()
{ return Interpreter::active_cpp_screen_interface->get_screen_height_in_units(); }

uint8_t cpp_get_font_width_in_units()
{ return Interpreter::active_cpp_screen_interface->get_font_width_in_units(); }

uint8_t cpp_get_font_height_in_units()
{ return Interpreter::active_cpp_screen_interface->get_font_height_in_units(); }

z_colour cpp_get_default_foreground_colour()
{ return Interpreter::active_cpp_screen_interface->get_default_foreground_colour(); }

z_colour cpp_get_default_background_colour()
{ return Interpreter::active_cpp_screen_interface->get_default_background_colour(); }

uint8_t cpp_get_total_width_in_pixels_of_text_sent_to_output_stream_3()
{ return Interpreter::active_cpp_screen_interface
  ->get_total_width_in_pixels_of_text_sent_to_output_stream_3(); }

int cpp_parse_config_parameter(char *key, char *value)
{ return Interpreter::active_cpp_screen_interface->parse_config_parameter(
    key, value); }

void cpp_link_interface_to_story(struct z_story *story)
{ Interpreter::active_cpp_screen_interface->link_interface_to_story(story); }

void cpp_reset_interface()
{ Interpreter::active_cpp_screen_interface->reset_interface(); }

int cpp_close_interface(z_ucs *error_message)
{ return Interpreter::active_cpp_screen_interface->close_interface(
    error_message); }

void cpp_set_buffer_mode(uint8_t new_buffer_mode)
{ Interpreter::active_cpp_screen_interface->set_buffer_mode(
    new_buffer_mode == true ? true : false); }

void cpp_z_ucs_output(z_ucs *z_ucs_output)
{ Interpreter::active_cpp_screen_interface->z_ucs_output(z_ucs_output); }

int16_t cpp_read_line(zscii *dest, uint16_t maximum_length,
    uint16_t tenth_seconds, uint32_t verification_routine,
    uint8_t preloaded_input, int *tenth_seconds_elapsed,
    bool disable_command_history, bool return_on_escape)
{ return Interpreter::active_cpp_screen_interface->read_line(dest,
    maximum_length, tenth_seconds, verification_routine, preloaded_input,
    tenth_seconds_elapsed, disable_command_history, return_on_escape); }

int cpp_read_char(uint16_t tenth_seconds,
    uint32_t verification_routine, int *tenth_seconds_elapsed)
{ return Interpreter::active_cpp_screen_interface->read_char(tenth_seconds,
    verification_routine, tenth_seconds_elapsed); }

void cpp_show_status(z_ucs *room_description, int status_line_mode,
    int16_t parameter1, int16_t parameter2)
{ Interpreter::active_cpp_screen_interface->show_status(room_description,
    status_line_mode, parameter1, parameter2); }

void cpp_set_text_style(z_style text_style)
{ Interpreter::active_cpp_screen_interface->set_text_style(text_style); }

void cpp_set_colour(z_colour foreground, z_colour background,
    int16_t window)
{ Interpreter::active_cpp_screen_interface->set_colour(foreground, background, window); }

void cpp_set_font(z_font font_type)
{ Interpreter::active_cpp_screen_interface->set_font(font_type); }

void cpp_split_window(int16_t nof_lines)
{ Interpreter::active_cpp_screen_interface->split_window(nof_lines); }

void cpp_set_window(int16_t window_number)
{ Interpreter::active_cpp_screen_interface->set_window(window_number); }

void cpp_erase_window(int16_t window_number)
{ return Interpreter::active_cpp_screen_interface->erase_window(window_number); }

void cpp_set_cursor(int16_t line, int16_t column, int16_t window)
{ Interpreter::active_cpp_screen_interface->set_cursor(line, column, window); }

uint16_t cpp_get_cursor_row()
{ return Interpreter::active_cpp_screen_interface->get_cursor_row(); }

uint16_t cpp_get_cursor_column()
{ return Interpreter::active_cpp_screen_interface->get_cursor_column(); }

void cpp_erase_line_value(uint16_t start_position)
{ Interpreter::active_cpp_screen_interface->erase_line_value(start_position); }

void cpp_erase_line_pixels(uint16_t start_position)
{ Interpreter::active_cpp_screen_interface->erase_line_pixels(start_position); }

void cpp_output_interface_info()
{ Interpreter::active_cpp_screen_interface->output_interface_info(); }

bool cpp_input_must_be_repeated_by_story()
{ return 
  Interpreter::active_cpp_screen_interface->input_must_be_repeated_by_story(); }


struct z_screen_interface Interpreter::cpp_screen_interface =
{
  &cpp_get_interface_name,
  &cpp_is_status_line_available,
  &cpp_is_split_screen_available,
  &cpp_is_variable_pitch_font_default,
  &cpp_is_color_available,
  &cpp_is_picture_displaying_available,
  &cpp_is_bold_face_available,
  &cpp_is_italic_available,
  &cpp_is_fixed_space_font_available,
  &cpp_is_timed_keyboard_available,
  &cpp_is_preloaded_input_available,
  &cpp_is_character_graphics_font_availiable,
  &cpp_is_picture_font_availiable,
  &cpp_get_screen_height,
  &cpp_get_screen_width,
  &cpp_get_screen_width_in_units,
  &cpp_get_screen_height_in_units,
  &cpp_get_font_width_in_units,
  &cpp_get_font_height_in_units,
  &cpp_get_default_foreground_colour,
  &cpp_get_default_background_colour,
  &cpp_get_total_width_in_pixels_of_text_sent_to_output_stream_3,
  &cpp_parse_config_parameter,
  &cpp_link_interface_to_story,
  &cpp_reset_interface,
  &cpp_close_interface,
  &cpp_set_buffer_mode,
  &cpp_z_ucs_output,
  &cpp_read_line,
  &cpp_read_char,
  &cpp_show_status,
  &cpp_set_text_style,
  &cpp_set_colour,
  &cpp_set_font,
  &cpp_split_window,
  &cpp_set_window,
  &cpp_erase_window,
  &cpp_set_cursor,
  &cpp_get_cursor_row,
  &cpp_get_cursor_column,
  &cpp_erase_line_value,
  &cpp_erase_line_pixels,
  &cpp_output_interface_info,
  &cpp_input_must_be_repeated_by_story
};


void Interpreter::register_screen_interface(ScreenInterface *screen_interface)
{
  Interpreter::active_cpp_screen_interface = screen_interface;
  c_fizmo::fizmo_register_screen_interface(&cpp_screen_interface);
}

void Interpreter::start(char* z_story_filename, char *blorb_filename,
    char *restore_on_start_filename)
{
  c_fizmo::fizmo_start(z_story_filename, blorb_filename,
      restore_on_start_filename);
}

void Interpreter::new_screen_size(int width, int height)
{
  c_fizmo::fizmo_new_screen_size(width, height);
}

zscii Interpreter::unicode_char_to_zscii_input_char(z_ucs unicode_char)
{
  return c_fizmo::unicode_char_to_zscii_input_char(unicode_char);
}

int Interpreter::streams_z_ucs_output(z_ucs *z_ucs_output)
{
  return c_fizmo::streams_z_ucs_output(z_ucs_output);
}

int Interpreter::streams_latin1_output(char *latin1_output)
{
  return c_fizmo::streams_latin1_output(latin1_output);
}

int Interpreter::i18n_translate(int string_code, ...)
{
  va_list ap;
  int result;

  va_start(ap, string_code);
  result = c_fizmo::_i18n_va_translate(
      string_code,
      ap);
  va_end(ap);

  return result;
}

int Interpreter::i18n_translate_and_exit(int string_code, int exit_code, ...)
{
  va_list ap;
  int result;

  va_start(ap, exit_code);
  result = c_fizmo::_i18n_va_translate(
      string_code,
      ap);
  va_end(ap);

  exit(exit_code);

  return result;
}

