// Arup Guha
// Solution to CIS 3362 Homework #2 Question #4: Adapted from CIS 3360 Program #1 Solution

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAXSTRING 100
#define MAXFILE 10000
#define MATSIZE 10
#define LINELEN 80

void encrypt(char plain[], int mat[][MATSIZE], int n);
void pad(char text[], int n);

int main() {

    char keyfile[MAXSTRING], inputfile[MAXSTRING], outputfile[MAXSTRING];

    FILE* ifp = fopen("hill.txt", "r");
    int n, i, j;

    // Read in the key.
    fscanf(ifp, "%d", &n);
    int mat[MATSIZE][MATSIZE];
    for (i=0; i<n; i++)
        for (j=0; j<n; j++)
            fscanf(ifp, "%d", &mat[i][j]);

    // Read in the message to encrypt.
    char plain[MAXFILE];
    fscanf(ifp, "%s", plain);
    fclose(ifp);

    // Do it!
    encrypt(plain, mat, n);
    return 0;
}

// Prints out the Hill cipher encryption of plain using the key mat of
// size n x n.

// Side-effect: plain will change to include padding characters.
void encrypt(char plain[], int mat[][MATSIZE], int n) {

    // Pad with x's first.
    pad(plain, n);

    // Loop through plain text.
    int i = 0;
    while (i < strlen(plain)) {

        int j, k;
        char cipher[MATSIZE+1];

        // Encrypt this block, storing in cipher.
        for (j=0; j<n; j++) {
            int value = 0;
            for (k=0; k<n; k++)
                value = (value + mat[j][k]*(plain[i+k] - 'a'))%26;
            cipher[j] = (char)('a' + value);
        }
        cipher[n] = '\0';
        i += n;

        // Print out.
        printf("%s", cipher);
    }
    printf("\n");

}

// Adds x's to the last block if necessary so that strlen(text) is
// a multiple of n.
void pad(char text[], int n) {

    // Calculate number of padding chars.
    int oldlen = strlen(text);
    int padding = (n - oldlen%n)%n;
    int newlen = oldlen + padding;

    // Go ahead and pad.
    int i;
    for (i=oldlen; i<newlen; i++)
        text[i] = 'x';
    text[newlen] = '\0';
}
