#include <stdlib.h>
#include <string.h>
#include "include/unicode.h"

static inline char multibyte_char_count(char input) {
    if (input == ANSI_ESCAPE) return 20;
    if ((input & BITMASK_1B) == RESULT_1B) return 1;
    if ((input & BITMASK_2B) == RESULT_2B) return 2;
    if ((input & BITMASK_3B) == RESULT_3B) return 3;
    if ((input & BITMASK_4B) == RESULT_4B) return 4;
    if ((input & BITMASK_CONT) == RESULT_CONT) return 10;
    return -1;
}

struct utf8_string parse_string(char * input) {
    int idx = 0;
    int counter = 0;
    char bytecount;
    struct utf8_string out;
    while (input[idx] != '\0' && idx < strlen(input)) { // first count how many
        bytecount = multibyte_char_count(input[idx]);
        switch (bytecount) {
            case 4:
                idx ++;
            case 3:
                idx++;
            case 2:
                idx++;
            case 1:
                idx++;
                counter ++;
                break;
            case 20:
                // ANSI escape sequences
                if ((input[idx+1]&ANSI_ESCAPE_BITMASK_3B) == ANSI_ESCAPE_RESULT_3B) { // among go to utf8 escape 1B 25 47
                    if ((input[idx+2] & ANSI_ESCAPE_BITMASK_EXT_4B) == ANSI_ESCAPE_RESULT_EXT_4B) { // go to utf8 no return 1B 25 2F 49
                        idx+=3;
                    } else {
                        idx+=2;
                    }
                } else {
                    idx++;
                }
            case 10:
            case -1:
                idx++;
                continue;
        }
    }

    out.chars = malloc(sizeof(struct utf8_char)*counter);
    memset(out.chars, 0, sizeof(struct utf8_char)*counter);
    idx = counter = 0;
    while (input[idx] != '\0' && idx < strlen(input)) { //fill string
        bytecount = multibyte_char_count(input[idx]);
        switch (bytecount) {
            case 1:
                out.chars[counter] = (struct utf8_char) {
                    .chars = {input[idx],0,0,0},
                    .count = 1
                };
                idx++;
                break;
            case 2:
                out.chars[counter] = (struct utf8_char) {
                    .chars = {input[idx],input[idx+1],0,0},
                    .count = 2
                };
                idx+=2;
                break;
            case 3:
                out.chars[counter] = (struct utf8_char) {
                    .chars = {input[idx],input[idx+1],input[idx+2],0},
                    .count = 3
                };
                idx+=3;
                break;
            case 4:
                out.chars[counter] = (struct utf8_char) {
                    .chars = {input[idx],input[idx+1],input[idx+2],input[idx+3]},
                    .count = 4
                };
                idx+=4;
                break;
            case 20:
                // ANSI escape sequences
                if ((input[idx+1]&ANSI_ESCAPE_BITMASK_3B) == ANSI_ESCAPE_RESULT_3B) { // among go to utf8 escape 1B 25 47
                    if ((input[idx+2] & ANSI_ESCAPE_BITMASK_EXT_4B) == ANSI_ESCAPE_RESULT_EXT_4B) { // go to utf8 no return 1B 25 2F 49
                        idx+=3;
                    } else {
                        idx+=2;
                    }
                } else {
                    idx++;
                }
            case 10:
            case -1:
                counter--;
                idx++;
                continue;
        }
        counter ++;
    }
    out.count = counter;
    return out;
}