// Jacob Gadberry
// Support code to help with decryption of CIS 3362 Homework 3 Problem 3
// 9/12/2024

public class Playfair {
    public static void main(String[] args) {
        // Place your cipher text here
        String cipher = "ranxrabuunimlgaelaumtienabovpdudnfaipbmlefsboctfmeztcxnlcixcvrpzmcudapfpapmadktipabifllipabzanxcflzstlunzalozmbaauilpfbiplmcqueidzpoztcxcqsabiqsufbiufsidkmtzsumlgsiadzbpnpamcnpazatrosblarafvapcsosnuicsabimcotubpymcudvromaienabprpamcodsldysienlpaprpfimdeoudapepynalstdhfvaldapasidvapbsucapmadklgbutoduztlglgcuzmbaautkpapamcnospudipfuhomadsbatisnlplgsmupilvolgduifqtsientkoqaplgsuhomadsticnprrfapvtykcfsdvroefqqiebcusiarpieaesbatapycixccsaqtbmcbatapycixclgdumefsbsblauidsrhoosudtvalkfqihqlgtlaetspolplguducmsucaphogamckppodktlplmcsqydduidnosblpapxgdudzponosbltdkaiftlplgsipdpubizuazscouembnmcumcofsmbfprpcnqehr";
        // Place your keyword here
        String keyWord = generatePlayfairKey("atlantis");
        // If you'd like to see the Playfair encryption matrix
        printMatrix(keyWord);
        // Store our key
        char key[][] = createKey(keyWord);
        // Decrypt the matrix 
        decrypt(cipher, key);
    }
    // Given the cipher text and the key (as the Playfair matrix), decrypt the ciphertext
    public static void decrypt(String cipher, char key[][]){
        int len = cipher.length();

        //Since the encryption works with digarms we increment by two characters at a time
        for(int i=0; i<len; i+=2){
            char firstLet = cipher.charAt(i);
            int[] firstPos = getLetterPosition(firstLet, key);
            char secondLet = cipher.charAt(i+1);
            int[] secondPos= getLetterPosition(secondLet, key);
            
            //Row Rule (the i values match) move left
            if(firstPos[0] == secondPos[0]){
                //In order to index to the left position, we can add 4, since when we mod it by 5 we get the same value 
                firstLet = (char)key[firstPos[0]][((firstPos[1]+4)%5)];
                secondLet = (char)key[secondPos[0]][((secondPos[1]+4)%5)];
            }
            //Column Rule (the j values match) move up
            else if(firstPos[1] == secondPos[1]){
                // Go up one row keeping the same column position 
                firstLet = (char)key[((firstPos[0]-1)+5)%5][firstPos[1]];
                secondLet = (char)key[((secondPos[0]-1)+5)%5][secondPos[1]];
            }
            //Box Rule (if the box rule is applied, essentially the letters trade column values)
            else{
                // Swap column and row numbers between the two letters
                firstLet = (char)key[firstPos[0]][secondPos[1]];
                secondLet = (char)key[secondPos[0]][firstPos[1]];
            }
            // Display the digraph
            System.out.print(""+firstLet+""+secondLet);
        }
    }

    //Takes in the proposed keyword and create the Playfair matrix based off of the key word
    public static char[][] createKey(String keyword){
        char [][]playfairMatrix = new char[5][5];
        int curIndex = 0; 
        for(int i=0; i<5; i++){
            for(int j=0; j<5; j++){
                playfairMatrix[i][j] = keyword.charAt(curIndex);
                curIndex++;
            }
        }
        return playfairMatrix;
    }

    //Takes the keyword and then generates a String of length 25 to store in a playfair matrix
    public static String generatePlayfairKey(String keyword){
        String newKeyword = keyword + "abcdefghiklmnopqrstuvwxyz";

        //Remove all duplicates of a letter
        for(int i=0; i<keyword.length(); i++){
            for(int j=i+1; j<newKeyword.length()-1; j++){
                // We've found a repeated letter
                if(newKeyword.charAt(i) == newKeyword.charAt(j)){
                    newKeyword = newKeyword.substring(0, j) + newKeyword.substring(j+1, newKeyword.length());
                }
            }
        }
        return newKeyword;
    }
    // Given the string representing the Playfair matrix
    // print out the table in human readable format
    public static void printMatrix(String key){
        for(int i=0; i<5; i++){
            for(int j=0; j<5; j++){
                if(j == 4)
                    System.out.print(key.charAt((i*5)+j));
                else
                    System.out.print(key.charAt((i*5)+j) + " | ");
            }
            System.out.println();
        }
    }
    // Get the (x,y) coordinantes of the letter in the key
    public static int[] getLetterPosition(char letter, char key[][]){
        int pos[] = new int[2];

        //Loop through the key and look for the letter
        for(int i=0; i<5; i++){
            for(int j=0; j<5; j++){
                //If we have found the letter, store the row and column
                if(key[i][j] == letter){
                    pos[0] = i;
                    pos[1] = j;
                    return pos;
                }
            }
        }
        return null;
    }
}
