#include "iden.h"
#include "lex.h"
#include "../print.h"
#include "../common.h"

static size_t strlen(const char* str) {
	size_t len = 0;
	while(*(str++))
		len++;
	return len;
}


extern u32 fg, bg;

void print_tok(struct token* tok) {
	u32 savebg = bg, savefg = fg;
    /* header: [file:row:col] */
    print("[");
    print(tok->file->name);
    print(":");
	if(tok->row + 1 < (1 << 16)) {
		print16(tok->row + 1);
		print(":");
		print16(tok->col + 1);
	} else {
		print32(tok->row + 1);
		print(":");
		print32(tok->col + 1);
	}
    print("] ");

    u32 color = fg;
    switch (tok->type) {
        case TOK_KEYWORD:
            color = 0xFF3322;
            print("keyword: ");
            print(keywords[tok->keyword]);
            print("\n");
            break;
        case TOK_NUM:
            color = 0x3322FF;
            print("number: ");
            print(" (");
            print64((unsigned long)tok->num);
            print("):\n");
            break;
        case TOK_IDEN: {
            color = 0x137FFF;
            struct iden* id = &identbl[tok->iden];
            print("iden: { .hash = 0x");
            print32(id->hash);
            print(", .data = \"");
            print(id->data);
            print("\" (");
            /* print pointer value as hex */
            print("ptr"); /* pointer printing omitted; add if needed */
            print("), .len = ");
            print32((int)id->len);
            print(" }:\n");
            break;
        }
        case TOK_OP: {
            color = 0xBEDEAD;
            print("operator: ");
            print(ops[tok->op]);
            print(" (#");
            print32(tok->op);
            print("):\n");
            break;
        }
        default: {
            color = 0x00FF00;
            /* print single char and hex */
            char c[2] = { (char)tok->type, 0 };
            print(c);
            print(" (0x");
            print32((unsigned char)tok->type);
            print("):\n");
            break;
        }
    }

    /* line with number and separator: "\t%4d | " */
    print("\t");
    /* pad row number to width 4 */
    {
        char numbuf[8];
        int len = 0;
        long r = tok->row + 1;
        if (r == 0) {
            numbuf[len++] = '0';
        } else {
            long tmp = r;
            char rev[8];
            int rp = 0;
            while (tmp) {
                rev[rp++] = '0' + (tmp % 10);
                tmp /= 10;
            }
            while (rp--) numbuf[len++] = rev[rp];
        }
        /* left pad with spaces to width 4 */
        for (int i = 0; i < 4 - len; ++i) print(" ");
        /* print number */
        for (int i = 0; i < len; ++i) {
            char s[2] = { numbuf[i], 0 };
            print(s);
        }
    }
    print(" | ");

    /* print text before token */
    if (tok->col > 0)
        printn(tok->file->lines[tok->row], tok->col);

    /* print token text */
    fg = color;
    if (tok->len > 0)
        printn(tok->file->lines[tok->row] + tok->col, tok->len);
    fg = savefg;
    bg = savebg;

    /* print rest of line after token */
    printn(tok->file->lines[tok->row] + tok->col + tok->len,
           strlen(tok->file->lines[tok->row] + tok->col + tok->len));

    /* caret line */
    print("\t     | ");
    for (int i = 0; i < tok->col; i++) {
        if (tok->file->lines[tok->row][i] == '\t') {
            print("\t");
        } else {
            print(" ");
        }
    }

	fg = bg;
	bg = ~fg;
    print("^");
	fg = savefg;
	bg = savebg;
    for (size_t i = 1; i < tok->len; i++) print("~");
    print("\n");
}


