#include "../../../l1_5/core/stringsearch.h"

void VecU64_fprint_debug_vivod(FILE* file, const VecU64* vec){
    for (size_t i = 0; i < vec->len; i++) {
        fprintf(file, "%lu ", vec->buf[i]);
    }
    fprintf(file, "\n");
}

VecU64 trivial_prefix_function(SpanU8 s){
    VecU64 prefix = VecU64_new_zeroinit(s.len + 1);
    for (size_t i = 0; i <= s.len; i++) {
        for (size_t k = 0; k < i; k++) {
            for (size_t j = 0; j < k; j++) {
                if (s.data[j] != s.data[i - k + j])
                    goto cnt;
            }
            prefix.buf[i] = k;
            cnt:
            continue;
        }
    }
    return prefix;
}

VecU64 trivial_z_function(SpanU8 s){
    VecU64 z = VecU64_new_zeroinit(s.len + 1);
    for (size_t i = 0; i <= s.len; i++) {
        for (size_t j = 0; i + j < s.len; j++) {
            if (s.data[j] != s.data[i + j])
                break;
            z.buf[i]++;
        }
    }
    return z;
}

void test_prefix_function(SpanU8 str){
    VecU64 correct = trivial_prefix_function(str);
    VecU64 my = prefix_function(str);
    if (!VecU64_equal_VecU64(&correct, &my)) {
        fprintf(stderr, "Test Pi  ");
        SpanU8_fprint(str, stderr);
        fprintf(stderr, "\n");
        fprintf(stderr, "Correct: ");
        VecU64_fprint_debug_vivod(stderr, &correct);
        fprintf(stderr, "My:      ");
        VecU64_fprint_debug_vivod(stderr, &my);
        abort();
    }
    VecU64_drop(correct);
    VecU64_drop(my);
}

void test_z_function(SpanU8 str){
    VecU64 correct = trivial_z_function(str);
    VecU64 my = z_function(str);
    if (!VecU64_equal_VecU64(&correct, &my)) {
        fprintf(stderr, "Test Z    ");
        SpanU8_fprint(str, stderr);
        fprintf(stderr, "\n");
        fprintf(stderr, "Correct: ");
        VecU64_fprint_debug_vivod(stderr, &correct);
        fprintf(stderr, "My:      ");
        VecU64_fprint_debug_vivod(stderr, &my);
        abort();
    }
    VecU64_drop(correct);
    VecU64_drop(my);
}

int main(){
    test_prefix_function(cstr(""));
    test_prefix_function(cstr("a"));
    test_prefix_function(cstr("ab"));
    test_prefix_function(cstr("aaaa"));
    test_prefix_function(cstr("aabbaabxxxaabbaab"));

    test_z_function(cstr(""));
    test_z_function(cstr("a"));
    test_z_function(cstr("aa"));
    test_z_function(cstr("aaa"));
    test_z_function(cstr("aaaa"));
    test_z_function(cstr("ab"));
    test_z_function(cstr("aba"));
    test_z_function(cstr("bbaa"));
    test_z_function(cstr("abacad"));

    test_prefix_function(cstr("hsooihoioifodoiwoihoiodisifoioihhhshshsshsoodfojoioow"));
    test_z_function(cstr("kdfkjpkjpksdpsdkpfpkspksfpksdpjpsdpdfjpospsdjpsdpfpspsf"));
    test_prefix_function(cstr("alkalaalkalakalkalakklakalalkalaakllaklakka"));
    test_z_function(cstr("alkalaalkalakalkalakklakalalkalaakllaklakka"));
}
