// Sushant Kulkarni
// Sample Solution to CIS 3362 Homework #3 Problem #6: ADFGVX encryption
// 10/5/2014

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

char step1[1000];
const int dim=6;
char message[500];
char keyword[100];
char adfgvx[] =  {"ADFGVX"};
char mat[dim][dim];
void reorder (char ** mat , int numcols, int numrows);
int main(){

	FILE *fp;
	fp = fopen("q6.txt", "r");

    // Read in matrix of characters.
	for (int i =0 ; i< dim; ++i)
		for (int j= 0; j<dim; ++j)
			fscanf(fp,"%c ",& mat[i][j] );

    // Read in second key and message.
	fgets(keyword, sizeof(keyword), fp);
	fgets(message,sizeof(message), fp);

	// Convert to upper case.
	int keywordLength = strlen(keyword) -1;
	for (int i=0; i< keywordLength; ++i){
		keyword[i] = keyword[i] + 'A' - 'a';
	}

	// Copy in ADFGVX code for each letter.
	for(int j = 0; j< strlen(message); ++j){
		for(int row = 0; row < dim; ++row){
			for (int col =0 ;col< dim; ++col){
				if (message[j] == mat[row][col]){
					step1[2*j] = adfgvx[row];
					step1[2*j+1] = adfgvx[col];
				}
			}
		}
	}

	// Calculate matrix size.
	int k=0;
	float num = strlen(step1)/ keywordLength;
	int numrows = ceil(num)+2;

    // Allocate memory.
	char ** step2;
	step2 = (char**) malloc(numrows*sizeof(char*));
	for (int i =0; i< numrows; ++i){
		step2[i] = (char*)malloc(sizeof(char) *keywordLength);
	}

	// Copy letters into transposed grid.
	int kk=0;
	for (int i =0; i< numrows; ++i){
		for (int j =0; j< keywordLength; ++j){
			if (i == 0){
				step2[i][j] = keyword[j];

			}
			else{
				if (step1[kk] != '\0'){
					step2[i][j] = step1[kk];
					kk += 1;
				}
				else{
					step2[i][j] = 'X';
				}
			}
		}
	}

    // Reorder columns.
	char * cipher_text;
	cipher_text = (char *)calloc(numrows*keywordLength, sizeof(char));
	reorder(step2, keywordLength, numrows);

    // Print out cipher text.
	int cipher_counter=0;
	printf("Cipher text \n");
	for (int j = 0; j< keywordLength; ++j){
		for (int i = 1; i< numrows; ++i){
			cipher_text[cipher_counter] = step2[i][j];
			printf("%c", cipher_text[cipher_counter]);
			cipher_counter += 1;
		}
	}

	// Manage memory.
	printf("\n");
	fclose(fp);
	free(step2);
	free(cipher_text);
	return 0;
}

// Runs a modified sort, which sorts the columns using the top column as the key.
void reorder (char ** mat , int numcols, int numrows){
	char temp;
	for (int i =0; i < numcols -1; ++i){
		for (int j = 0; j< numcols - i -1; ++j){
			if( (mat[0][j] - 'A') > (mat[0][j+1] - 'A')){
				for (int k =0; k< numrows; ++k){
					temp = mat[k][j];
					mat [k][j] = mat [k][j+1];
					mat[k][j+1] = temp;
				}
			}
		}
	}
}
