// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "include/challenges.h"

char genChallenge(FILE * stream, char ** output, challenge_t challenge) {
    printf("------------- DESAFIO -------------\n");
    printf("%s\n\n", challenge.message);

    if (challenge.function != NULL)
        challenge.function();

    printf("\n----- PREGUNTA PARA INVESTIGAR -----\n");
    printf("%s\n\n", challenge.question);
    
    size_t linecap = 0;
    if (getline(output, &linecap, stream) < 0)
        printSystemError("Challenges: getline()");

    int ans = strcmp(*output, challenge.flag);
    return !ans;
}

void writeChallenge() {
    if (write(0xd, "................................La respuesta es fk3wfLCm3QvS\n", 61) < 0)
        perror("write");
}

void filterChallenge() {
    char * ans = "La respuesta es K5n2UFfpFMUN\n";
    int i = 0;
    while (ans[i] != '\0') {
        double fdRandom = getUniform(1);
        if (fdRandom <= 0.25) {
            if (write(STDOUT_FILENO, ans + i++, 1) < 0)
                printSystemError("Challenges: write()");
        }
        else {
            for (int j = (int) getUniform(3) + 1; j > 0; j--) {
                int randNum = (int) getUniform(90);
                char randLetter = (char) (randNum + '#');
                if (write(STDERR_FILENO, &randLetter, 1) < 0)
                    printSystemError("Challenges: write()");
            }
        }
    }
}

void questionChallenge() {
    if (write(STDOUT_FILENO, "\33[30;40m", 8) < 0)
        printSystemError("Challenges: write()");
    if (write(STDOUT_FILENO, "La respuesta es BUmyYq5XxXGt", 28) < 0)
        printSystemError("Challenges: write()");
    if (write(STDOUT_FILENO, "\33[0m\n", 5) < 0)
        printSystemError("Challenges: write()");
}

void quineChallenge() {
    int outputGCC = system("gcc quine.c -o quine");
    if (outputGCC < 0)
        printSystemError("Challenges: system()");

    if (outputGCC == 0) {
        printf("¡Genial!, ya lograron meter un programa en quine.c, veamos si hace lo que corresponde.\n");
        int outputDIFF = system("./quine | diff quine.c -");
        if (outputDIFF < 0)
            printSystemError("Challenges: system()");

        if (outputDIFF == 0)
            printf("La respuesta es chin_chu_lan_cha\n");
        else
            printf("\ndiff encontró diferencias.\n");

        if (system("rm quine") < 0)
            printSystemError("Challenges: system()");
    }
    else
        printf("\nENTER para reintentar.\n");
}

void gdbme(char * output) {
    if (getpid() == 0x12345678) {
        *output = 1;
    }
    else *output = 0;
}

void gdbChallenge() {
    char gdbOutput;
    gdbme(&gdbOutput);

    if (gdbOutput)
        printf("La respuesta es gdb_rules\n");
    else
        printf("ENTER para reintentar.\n");
}

void boxMuller(double * normal) {
    double random1 = getUniform(1);
    double random2 = getUniform(1);
    *normal = sqrt(-2 * log(random1)) * cos(2 * M_PI * random2);
}

void normalChallenge() {
    for (int i = 0; i < MAX_NORMALS; i++) {
        double normal = 0;
        boxMuller(&normal);
        printf("%.6f ", normal);
    }
    printf("\n");
}