/**
 *  This is where it all begins.
 *
 *  Author: Ramkumar Natarajan (nrk@cs.purdue.edu)
 **/

#include "main.h"

LOCAL char *readInput(FILE *fp) {
    char *retp  = NULL;
    int   curp  = 0, ch;
    int   cursz = EXP_INP_SZ_;

    retp = my_malloc(sizeof *retp * cursz);

    while ( (ch = fgetc(fp)) != EOF ) {
        if ( curp >= cursz ) {
            retp   = my_realloc(retp, sizeof *retp * (cursz + EXP_INP_SZ_));
            cursz += EXP_INP_SZ_;
        }
        retp[curp++] = ch;
    }

    if ( !curp ) {
        MY_FREE(retp);
        return NULL;
    }

    if ( retp[curp-1] == '\n' ) {
        retp = my_realloc(retp, sizeof *retp * curp);
        retp[curp-1] = 0;
    }
    else {
        retp       = my_realloc(retp, sizeof *retp * (curp + 1));
        retp[curp] = 0;
    }
    return retp;
}

LOCAL void printCipherMap(CipherText *ctptr) {
    int i, j;
    CipherChar *ccptr = ctptr->ciphermap;
    int  *ciphermap  = ctptr->plainmap;
    char *plainchars = ctptr->plainchars;

    for ( i = 0; i < ALPHA_SZ_; ++i ) {
        int current = ciphermap[i];

        if ( !ccptr[i].isPresent )
            continue;
        printf("%c => ", 'a' + i);
        if ( plainchars[i] == '?' ) {
            current = ciphermap[i];
            for ( j = 0; j < ALPHA_SZ_; ++j ) {
                if ( current & aleph_codes[j] ) {
                    printf("%c", 'a' + j);
                    current &= ~aleph_codes[j];
                    if ( current )
                        printf(", ");
                }
            }
        }
        else
            printf("%c", plainchars[i]);
        printf("\n");
    }
}

int main(int argc, char *argv[]) {
    char *txt;
    CipherText gctxt;
    clock_t start, end;
    double duration;
    int unsolved;

    if ( argc <= 1 )
        txt = readInput(stdin);
    else {
        FILE *fp = fopen(argv[1], "r");
        if ( !fp ) {
            perror("fopen failed");
            fprintf(stderr, "Input file couldn't be opened\n");
            exit(EXIT_FAILURE);
        }
        txt = readInput(fp);
    }
    if ( !txt ) {
        fprintf(stderr, "No input given!!\n");
        exit(EXIT_FAILURE);
    }
    
    start = clock();
    unsolved = solveQuip(txt, &gctxt);
    end = clock();

    if ( !unsolved ) {
        printf("Original Text:\n");
        printf("%s\n\n", gctxt.ociphertxt);
        printf("Deciphered Text:\n");
        printf("%s\n\n", gctxt.plaintxt);
        printf("Cipher to Plain text mapping:\n");
        printf("-----------------------------\n");
        printCipherMap(&gctxt);
        duration = (double) (end - start) / CLOCKS_PER_SEC;
        printf("Solving time: %2.1f seconds\n", duration);
    }
    else
        exit(EXIT_FAILURE);
    
    return 0;
}
