#include <termcap.h>
#include "lesstest.h"

extern TermInfo terminfo;

// Set the user's terminal to a given attribute and colors.
static void display_attr_color(Attr attr, Color fg_color, Color bg_color) {
       printf("\33[m");
       if (fg_color != NULL_COLOR)
               printf("\33[%dm", fg_color);
       if (bg_color != NULL_COLOR)
               printf("\33[%dm", bg_color);
       if (attr & ATTR_UNDERLINE)
               printf("%s", terminfo.enter_underline);
       if (attr & ATTR_BOLD)
               printf("%s", terminfo.enter_bold);
       if (attr & ATTR_BLINK)
               printf("%s", terminfo.enter_blink);
       if (attr & ATTR_STANDOUT)
               printf("%s", terminfo.enter_standout);
}

static int hexval(unsigned char ch) {
       if (ch >= '0' && ch <= '9') return ch - '0';
       if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
       if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
       fprintf(stderr, "invalid hex char 0x%x\n", ch);
       abort();
}

static int get_hex(unsigned char const** pp) {
       int v1 = hexval(*(*pp)++);
       int v2 = hexval(*(*pp)++);
       return (v1 << 4) | v2;
}

// Display a given screen image on the user's terminal.
void display_screen(const byte* img, int imglen, int screen_width, int screen_height) {
       int x = 0;
       int y = 0;
       int cursor_x = 0;
       int cursor_y = 0;
       int literal = 0;
       Attr curr_attr = 0;
       Color curr_fg_color = NULL_COLOR;
       Color curr_bg_color = NULL_COLOR;
       while (imglen-- > 0) {
               wchar ch = load_wchar(&img);
               if (!literal) {
                       switch (ch) {
                       case '\\':
                               literal = 1;
                               continue;
                       case LTS_CHAR_ATTR:
                               curr_attr = get_hex(&img);
                               display_attr_color(curr_attr, curr_fg_color, curr_bg_color);
                               continue;
                       case LTS_CHAR_FG_COLOR:
                               curr_fg_color = get_hex(&img);
                               display_attr_color(curr_attr, curr_fg_color, curr_bg_color);
                               continue;
                       case LTS_CHAR_BG_COLOR:
                               curr_bg_color = get_hex(&img);
                               display_attr_color(curr_attr, curr_fg_color, curr_bg_color);
                               continue;
                       case LTS_CHAR_CURSOR:
                               cursor_x = x;
                               cursor_y = y;
                               continue;
                       }
               }
               literal = 0;
               if (ch != 0) {
                       byte cbuf[UNICODE_MAX_BYTES];
                       byte* cp = cbuf;
                       store_wchar(&cp, ch);
                       fwrite(cbuf, 1, cp-cbuf, stdout);
               }
               if (++x >= screen_width) {
                       printf("\n");
                       x = 0;
                       if (++y >= screen_height)
                               break;
               }
       }
       printf("%s", tgoto(terminfo.cursor_move, cursor_x, cursor_y));
       fflush(stdout);
}

// Print a given screen image on stderr.
// Unlike display_screen which prints escape sequences to change color etc,
// display_screen_debug only prints printable ASCII.
void display_screen_debug(const byte* img, int imglen, int screen_width, int screen_height) {
       int x = 0;
       int y = 0;
       int literal = 0;
       while (imglen-- > 0) {
               wchar ch = load_wchar(&img);
               if (!literal) {
                       switch (ch) {
                       case '\\':
                               literal = 1;
                               continue;
                       case LTS_CHAR_ATTR:
                       case LTS_CHAR_FG_COLOR:
                       case LTS_CHAR_BG_COLOR:
                               x -= 3; // don't count LTS_CHAR or following 2 bytes
                               break;
                       case LTS_CHAR_CURSOR:
                               x -= 1; // don't count LTS_CHAR
                               break;
                       }
               }
               literal = 0;
               if (is_ascii(ch))
                       fwrite(&ch, 1, 1, stderr);
               else
                       fprintf(stderr, "<%lx>", (unsigned long) ch);
               if (++x >= screen_width) {
                       fprintf(stderr, "\n");
                       x = 0;
                       if (++y >= screen_height)
                               break;
               }
       }
       fflush(stderr);
}

// Print a list of strings.
void print_strings(const char* title, char* const* strings) {
       if (1) return; ///
       fprintf(stderr, "%s:\n", title);
       char* const* s;
       for (s = strings; *s != NULL; ++s) {
               fprintf(stderr, " ");
               const char* p;
               for (p = *s; *p != '\0'; ++p) {
                       if (is_ascii(*p))
                               fprintf(stderr, "%c", (char) *p);
                       else
                               fprintf(stderr, "\\x%04x", *p);
               }
               fprintf(stderr, "\n");
       }
       fprintf(stderr, "%s- end\n", title);
}