import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.util.Random;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class VigenereFileStreamCipher {
    
    public VigenereFileStreamCipher() throws IOException {
        String keyString = "The snow lay thick on the steps.";
        //String keyString = "Florida";
        char[] keyArray = keyString.toCharArray();
        int[] key = new int[keyArray.length];
        for(int i = 0; i < keyArray.length; i++ ) {
            key[i] = keyArray[i];
        } // end for
        while( true ) {
            String plaintextFileName = JOptionPane.showInputDialog("Enter plaintext file name.","VigenereFileStreamCipher.java");
            if( plaintextFileName == null ) break;
            
            String outString = "";
            outString += "Plaintext is\n " + getFile(plaintextFileName) + "\n\n";
            
            String ciphertextFileName = "Encrypted"+plaintextFileName;
            encrypt(plaintextFileName,key,ciphertextFileName);
            
            outString += "Encrypted message is\n " + getFile(ciphertextFileName) + "\n\n";
            
            String decryptedFileName = "Decrypted"+plaintextFileName;
            decrypt(ciphertextFileName,key,decryptedFileName);
            
            outString += "Decrypted message is\n" + getFile(decryptedFileName) + " \n\n";
            JTextArea outArea = new JTextArea(outString,30,60);
            JOptionPane.showMessageDialog(null,new JScrollPane(outArea));
        } // end while
    } // end constructor
    
    void encrypt(String inFilename, int[] key, String outFileName) throws IOException {
        FileInputStream in = new FileInputStream(inFilename);
        FileOutputStream out = new FileOutputStream(outFileName);
        int next;
        int i = 0;
        int numBytes = 0;
        while( (next = in.read()) != -1 ) {
            byte b = (byte)(((byte)next + key[i])%256);
            i = (i+1)%key.length;
            String hexCode = convertToHex(b);
            out.write((byte)hexCode.charAt(0));
            out.write((byte)hexCode.charAt(1));
            numBytes++;
            if( numBytes % 40 == 0 ) {
                out.write((byte)'\n');
                numBytes = 0;
            } // end if
        } // end while
        in.close();
        out.close();
    }// end encrypt
    
    void decrypt(String inFilename, int[] key, String outFileName) throws IOException {
        FileInputStream in = new FileInputStream(inFilename);
        FileOutputStream out = new FileOutputStream(outFileName);
        int next;
        int i = 0;
        while( (next = in.read()) != -1 ) {
            if( (char)next == '\n' ) next = in.read();
            if( next == -1 ) break;
            byte nextByte1 = (byte)next;
            byte nextByte2 = (byte)in.read();
            String decodeString = (char)nextByte1 + "" + (char)nextByte2;
            byte decodeByte = (byte)Integer.parseInt(decodeString,16);
            byte outByte = (byte)((decodeByte-key[i]+256)%256);
            i = (i+1)%key.length;
            out.write(outByte);
        } // end while
        in.close();
        out.close();
    }// end decrypt
    
    public static void main(String[] a)throws IOException {
        new VigenereFileStreamCipher();
    } // end main
    
    String getFile(String fileName) throws IOException {
        FileInputStream in = new FileInputStream(fileName);
        int next;
        StringBuffer message = new StringBuffer();
        while( (next = in.read()) != -1 ) {
            byte nextByte = (byte)next;
            message.append((char)nextByte);
        } // end while
        in.close();
        return message.toString();
    }  // end getMessage
    
    public final void permute(char[] chars) {
        Random r = new Random();
        for( int i = 1; i < chars.length; i++ ) {
            char ch = chars[i];
            int j = r.nextInt(i);
            chars[i] = chars[j];
            chars[j] = ch;
        } // end for
    } // end permute
    
    public String convertToHex(byte b) {
        String hex = Integer.toString(b&0xFF,16).toUpperCase();
        if( hex.length() == 1 ) hex = "0" + hex;
        return hex;
    } // end convertToHex
    
} // end VigenereFileStreamCipher
