// Arup Guha
// 8/30/07
// Part of the Solution to Fall 2007 CIS 3360: Homework #1
// This code decrypts a file encoded by a transposition cipher, as specified
// in the problem description

import java.util.*;
import java.io.*;

public class DecryptTrans {
		
	private String cipher;
	private String key;
	private int[] perm;
	
	
	// Creates a DecryptTrans object, which basically sets up everything for
	// decryption.
	public DecryptTrans(Scanner file, String thekey) {
		
		cipher = "";
		
		// Read in the whole cipher text and store it into the String cipher.
		while (file.hasNext()) {
			String tmp = file.next();
			cipher = cipher + tmp;
		}
		
		// Set the key.
		key = thekey;
		
		// Set up the permutation matrix which is based on the key.
		perm = new int[key.length()];
		setPerm();
	}
	
	// Decrypts this object and returns the result as a String.
	public String decrypt() {
		
		// Calculating the dimensions of the grid to store the characters.
		int numcols = key.length();
		int numrows = cipher.length()/key.length();
		
		// If the message length isn't divisible by the keyword length,
		// something is wrong. Just return null to signify this.
		if (cipher.length()%key.length() != 0) return null;
		
		// Now, we can go and allocate space for the grid.
		char[][] grid = new char[numrows][numcols];
		
		int mycnt = 0;
		
		// Now, we look through each column of the grid.
		for (int i=0; i<perm.length; i++) {
			
			// Copy each letter from the ciphertext into the correct
			// grid column, which is perm[i].
			for (int j=0; j<numrows; j++)
				grid[j][perm[i]] = cipher.charAt(mycnt++);
		}
		
		String plain = "";
		
		// Recover the plaintext from the grid and store it into a String.
		for (int i=0; i<numrows; i++) 
			plain = plain + new String(grid[i]);
		
		return plain; // We are done =)
		
	}
	
	// Sets up the permuation array based on the key word.
	public void setPerm() {
		
		// Loop through each letter in the key word to figure out its "rank"
		// amongst the rest of the letters in the key word.
		for (int i=0; i<key.length(); i++) {
			
			// Counting the number of characters in the keyword that come
			// BEFORE character i, alphabetically. 
			int numCharsBefore = 0;
			for (int j=0; j<key.length(); j++) {
			
				// The first condition is sufficient for this assignment.
				// However, the second operand to the OR allows this to
				// work with keywords that HAVE repeated letters. In this
				// case, the copy of the letter that appears later has a
				// higher number.
				if ((key.charAt(j) < key.charAt(i)) || (key.charAt(j) == key.charAt(i) && j < i))
					numCharsBefore++;
			}
					
			// numCharsBefore represents the order in which column i was read
			// into the grid.
			perm[numCharsBefore] = i;
		}
	}
	
	// Writes message to the file referenced by out.
	public static void writeOutputFile(String message, BufferedWriter out) throws IOException {
		
		int cnt = 0;
		
		// Loop through each character.
		while (cnt < message.length()) {
			
			// Write this one out.
			out.write(message.charAt(cnt));
			cnt++;
			
			// Go to the next line after every 60 characters.
			if (cnt%60 == 0)
				out.write("\n");
		}
	}
	
	public static void main(String[] args) throws IOException {
		
		Scanner stdin = new Scanner(System.in);
		
		// Get the necessary information from the user.
		System.out.println("Enter the name of the file to be decrypted.");
		String filename = stdin.next();
		
		System.out.println("Enter your secret keyword for decryption.");
		String key = stdin.next();
		
		System.out.println("What is the name of the file where you want the output stored?");
		String outputfilename = stdin.next();
		
		Scanner fin = new Scanner(new File(filename));
		
		// Decrypt the messages.
		DecryptTrans thismessage = new DecryptTrans(fin, key);
		String ans = thismessage.decrypt();
		
		// Write the recovered plaintext to the output file.
		BufferedWriter out = new BufferedWriter(new FileWriter(outputfilename));
		writeOutputFile(ans, out);
		out.close();
	}
	
}