// Code from previous TA Jade Bowyer
// 9/7/20
// Helper code for CIS 3362 Homework 3 Problem 3
// Finds relative shifts to the first letter bin to determine
// 26 possible keys.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char * argv[]) {
	int i, j, k, length, n;
	char * key;

	//user inputs the ciphertext
	char ciphertext[1000];
	printf("Enter the ciphertext:\n");
	scanf("%s", ciphertext);
	length = strlen(ciphertext);

	//user inputs the key length
	printf("Enter the key length:\n");
	scanf("%d", &n);
	key = (char *)malloc(sizeof(char) * (n+1));

	int freq[n][26];
	int size[n];

	//initializes bins' frequency arrays
	for (i = 0; i < n; i++)
		for (j = 0; j < 26; j++)
			freq[i][j] = 0;

    //initializes bins' size arrays
	int div = length/n, r = length%n;
	for (i = 0; i < n; i++)
		size[i] = div;
	if (r != 0)
		for (i = 0; i < r; i++)
			size[i]++;

    //populates bins' frequency arrays
	for (i = 0; i < length; i++)
		freq[i%n][ciphertext[i]-'a']++;

	key[0] = 'a';
	key[n] = '\0';

	//consider each bin
	for (i = 1; i < n; i++) {
		int target = -1;
		double MIC = 0.0, max = 0.0;
		printf("\nComparing Bin 0 and Bin %d\n", i);
		printf("Shift\tMIC\n");
		//consider each shift of the bin
		for (j = 0; j < 26; j++) {
            //calculating the MIC for each shift
			int top = 0, bottom = size[i]*size[0];
			for (k = 0; k < 26; k++)
				top += freq[0][k]*freq[i][(k+j)%26];
			MIC = ((double)top)/bottom;
			printf("%d - '%c':\t%lf\n", j, j+'A', MIC);

            //finding the optimal shift
			if (MIC > max) {
				max = MIC;
				target = j;
			}
		}
		//printing optimal shift
		printf("Highest MIC with shift of %d or %c.\n\n", target, target+'A');
		key[i] = target+'a';
	}

	//printing out all potential keys
	printf("Shifted key: %s.\n", key);
	printf("All shifts of the key:\n");
	printf("Shift\tKey\n");
	for (i = 0; i < 26; i++) {
		char * shifted = (char *)malloc(sizeof(char)*(n+1));
		shifted = strcpy(shifted,key);
		for (j = 0; j < n; j++)
			shifted[j] = (shifted[j]-'a'+i)%26 + 'a';
		printf("%d\t%s\n", i, shifted);
	}

	//user selects a key
	printf("Enter the key you desire to decrypt the ciphertext with:\n");
	scanf("%s",key);

	//printing out plaintext
	for (i = 0; i < length; i++) {
		printf("%c", (ciphertext[i] - key[i%n] + 26)%26 + 'a');
	}

	return 0;
}