// 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 msg, as specified
// in the problem description

import java.util.*;
import java.io.*;

public class EncryptTrans {
		
	private String msg;
	private String key;
	private int[] perm;
	
	
	// Sets up the EncryptTrans object to be ready for encryption.
	public EncryptTrans(Scanner file, String thekey) {
		
		msg = "";
		
		// Read in the whole msg text and store it into the String msg.
		while (file.hasNext()) {
			String tmp = file.next();
			msg = msg + tmp;
		}
		
		// Set the key.
		key = thekey;
		
		// Set up the permutation matrix which is based on the key.
		perm = new int[key.length()];
		setPerm();
	}
	
	// Encrypts the current object and returns the result as a String.
	public String encrypt() {
		
		// Calculating the dimensions of the grid to store the characters.
		int numcols = key.length();
		
		// Pad the plaintext with X's as necessary.
		while (msg.length()%key.length() != 0) 
			msg = msg + "X";
			
		// Now we can calculate the number of rows in our grid.
		int numrows = msg.length()/numcols;
		
		// Now, we can go and allocate space for the grid.
		char[] cipher = new char[numrows*numcols];
		
		int mycnt = 0;
		
		// Now, we look through each column of the grid.
		for (int i=0; i<perm.length; i++) {
			
			// Find the next letter in the plaintext and copy that into the
			// correct ciphertext location. Namely, we are looking in row j
			// and column perm[i].
			for (int j=0; j<numrows; j++)
				 cipher[mycnt++]= msg.charAt(j*numcols+perm[i]);
		}
		
		// Return the ciphertext as a String.
		return new String(cipher);
		
	}
	
	// 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 encrypted.");
		String filename = stdin.next();
		
		System.out.println("Enter your secret keyword for encryption.");
		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));
		
		// Encrypt the messages.
		EncryptTrans thismessage = new EncryptTrans(fin, key);
		String ans = thismessage.encrypt();
		
		// Write the ciphertext to the output file.
		BufferedWriter out = new BufferedWriter(new FileWriter(outputfilename));
		writeOutputFile(ans, out);
		out.close();
	}
	
}