import java.util.*;
import java.lang.*;
import java.io.*;

/*
Usage: java sg1 [-e|-d] [inputfilename] [cipherkeyfilename] [outputfilename]

-e means to encode the flat text file

-d means to decode a file that was previously encoded
*/


public class sg1 {

public static String charlist="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*+-<>.,?/|][_={}:()~;' È�[8;1HÐÛÔíäû£ÜÊÖ¼Òïºö°ÉìùÃË¾ÝµÀóþâÚêÕýçÓú½ñÑá¢±Áð¡Äÿ¿\"";
//public static String charlist="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*+-<>.,?/|][_={}:()~;' \"";

private static String keypassphrase; 

public static void main(String argc[]){

String prepadding="";
String postpadding="";
String passphrase="";
String finaltext="";
String inputtext="";
String mymessage="";

//assign the input arguments to variables
String cmd=argc[0]; //cmd can be only -e or -d;
String inputfile=argc[1];
String cypherkeyfile=argc[2];
String outputfile=argc[3];

//open the input file and read in it completely
try{
BufferedReader in=new BufferedReader(new FileReader(inputfile));
String str;
	while((str=in.readLine())!=null) {
		inputtext+=str+"\n";
	}
in.close();
	//strip off that last carriage return; we do not want it!
	inputtext=inputtext.substring(0,inputtext.length()-1);
}catch(Exception e){}

Hashtable cypherhash=new Hashtable();
//open the cipherkeyfile and assign the passphrasekey to a variable, then add each key line to a hashtable entry with the name of the first char being the key's reference

try{
BufferedReader in=new BufferedReader(new FileReader(cypherkeyfile));
	String str;
	keypassphrase=in.readLine();
	str=in.readLine(); //just read in that blank line in cipher file format
	while((str=in.readLine())!=null) {
		//add this key line to the hashtable with the first char as its reference name
		cypherhash.put(str.substring(0,1),str);	
	}

}catch(Exception le){}

if(cmd.equals("-e")) {
//generate a random number of characters to preprend to our message
	//generate a random num between 0-150 and subtract from 300
	Random r1=new Random();
	int garbagechars=300-r1.nextInt(150);
	//generate a random sequence of chars from the charlist
	Random r2=new Random();
	for (int i=0;i<garbagechars;i++) {
		prepadding=prepadding+""+keypassphrase.charAt(r2.nextInt(keypassphrase.length()));
	}
//append the beginning delimeter to the above
	mymessage=prepadding+"<<<START:     ";
//append the text message pulled from the input file
	mymessage=mymessage+inputtext;
//append the ending delimeter to the above
	mymessage=mymessage+"      :END>>>";
//generate a random number of characters to append to the above
	Random r3=new Random();
	int endgarbagechars=300-r3.nextInt(150);
	for (int i=0;i<endgarbagechars;i++) {
		postpadding=postpadding+""+keypassphrase.charAt(r3.nextInt(keypassphrase.length()));
	}

//now add the postpadding to the message
	mymessage=mymessage+postpadding;
}

//now ask the user to input their passphrase
try{

	DataInputStream din=new DataInputStream(System.in);
	System.out.print("Enter your passphrase, but make sure no one is watching: ");
	System.out.flush();
	passphrase=din.readLine();
}catch(Exception me){System.out.println(""+me);}

Hashtable encodekeys=new Hashtable();
String newpassphrase="";

//now encode the passphrase to a new encoded passphrase
	//Basically, each char in the user passphrase is encoded this way:
	for (int j=0;j<passphrase.length();j++) {
	//grab a char in the passphrase
		String oldc=""+passphrase.charAt(j);
	//find it's corresponding index position in passphrasekey
		int coreindex=keypassphrase.indexOf(oldc);
	//load the key line with the first char's name in the hashtable above
		String keyline=(String)cypherhash.get(""+oldc);
	//Use the index position of the char to pull the encoded char out
		String newc=""+keyline.charAt(coreindex);
	//append that char to a encoded key string
		newpassphrase=newpassphrase+newc;
	//load the key line of that encoded char into a new hashtable
		encodekeys.put(newc,(String)cypherhash.get(""+newc));
	//repeat until the entire passphrase is encoded
	
	if(cmd.equals("-e")) {
		finaltext=encode(mymessage,newpassphrase,encodekeys,keypassphrase);
	} else {

		if(cmd.equals("-d")) {
			finaltext=decode(inputtext,newpassphrase,encodekeys,keypassphrase);
		
		} else {

		System.exit(0);
		}

	}
}		
//write final encoded text out to a file. 
	try{
		BufferedWriter out=new BufferedWriter(new FileWriter(outputfile));
		out.write(finaltext);
		out.close();

	}catch(Exception se){}


}//end main

public static String encode (String mymessage,String newpassphrase,Hashtable encodekeys,String keypassphrase) {
 
String finaltext="";

                int newpassphraselen=newpassphrase.length();
                int currentpos=0;//marks where we are in the order of keys
//encode the text above
        //Basically, the text of mymessage is encoded this way:
        for (int k=0;k<mymessage.length();k++) {

        //grab the first char of mymessage
                String messagec=""+mymessage.substring(k,k+1);
		if(messagec.equals("\n")){
		finaltext=finaltext+"\n";
		} else {
		if(messagec.equals("\t")){
		finaltext=finaltext+"\t";
		} else {
		if(messagec.equals("\\")) {
		finaltext=finaltext+"\\";
                } else {
        //using the first key line, encode the char by mapping its index point
	//in keypassphrase to a new encode char at the same index position in the first key

                if(currentpos == newpassphraselen) {currentpos=0;}
                String currentkey=(String)encodekeys.get(""+newpassphrase.substring(currentpos,currentpos+1));
                int oldcindex=keypassphrase.indexOf(""+messagec);
                finaltext=finaltext+""+currentkey.charAt(oldcindex);
        //continually rotate keys through the encoding of each char of mymessage

                currentpos++;
                }
        }
}

}

return finaltext;
}//end encode method

public static String decode (String inputtext, String newpassphrase, Hashtable encodekeys, String keypassphrase) {

String finaltext="";


int newpassphraselen=newpassphrase.length();
                int currentpos=0;
//decode the text above
        //Basically, the text of mymessage is decoded this way:
        for (int k=0;k<inputtext.length();k++) {

        //grab the first char of mymessage
		String messagec=""+inputtext.substring(k,k+1);
		if(messagec.equals("\n")) {
                        finaltext=finaltext+"\n";
                } else {
                if(messagec.equals("\t")) {
                        finaltext=finaltext+"\t";
                }else {
                if(messagec.equals("\\")) {
                        finaltext=finaltext+"\\";
                } else {
        //using the first key line, decode the char by mapping its index point in keypassphrase to a new encode char at the same index position in the first key line
                if(currentpos == newpassphraselen) {currentpos=0;}
                String currentkey=(String)encodekeys.get(""+newpassphrase.substring(currentpos,currentpos+1));
                //int oldcindex=keypassphrase.indexOf(""+messagec);
                int oldcindex=currentkey.indexOf(messagec);
                finaltext=finaltext+""+keypassphrase.substring(oldcindex,oldcindex+1);
        //continually rotate keys through the encoding of each char of mymessage.
                currentpos++;
                }
        }
}
}
return finaltext;
}//end decode method


}//end class
