/* James Little 5-5-01 
   I hope this is one of the last programs I have to write in this course.
*/

package jlittle_ex9;

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

public class App {
    private static App a;
    private static BitStreamInputStream reader;
    private static BitStreamOutputStream writer;
    private static String outFile;

    public static void main(String [] args){
	String inFile = null;
	System.out.println("input file is now input");
	inFile = "BitStreamInputStream.java";
	outFile = inFile+".LZW";
	
	try{
	    reader = new BitStreamInputStream(new FileInputStream(inFile));
	    writer = new BitStreamOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)), 12);
	} catch (FileNotFoundException e) {
	    System.out.println("flying pigs in space!!!!!!!!!! "+e);
	}

	a = new App();
	a.compress();
	a.decompress();	
    }
    
    // compression routine
    public void compress(){
	
	int MAX_VALUE = 4000;
	Vector string_table = new Vector();

	for(int i=0; i<256; i++){
	    string_table.add(String.valueOf((char)i));
	}

	System.out.println("I am now compressing...");
	int next_code = 256, intStr = 0, intChar=0;
	
	try{
	    intStr = reader.read();
	    String aString = String.valueOf((char)intStr);
	    String nextChar = "";
	    int i = 0;
	
	    while((intChar = reader.read())!=-1){
		
		nextChar = String.valueOf((char)intChar);
		if(string_table.contains(aString + nextChar)){
		    aString = aString + nextChar;
		}else{
		    i = string_table.indexOf(aString);
		    writer.writeBitField(i);
		    string_table.add(aString + nextChar);
		    aString = nextChar;
		} // end if		
		if(string_table.size()>MAX_VALUE){
		    string_table.removeAllElements();	
		    for(int j=0; j<256; j++){
			string_table.add(String.valueOf((char)j));
		    }
		}
	    } // end while
	    
	    i = string_table.indexOf(aString);
	    writer.writeBitField(i); // write a string
	    writer.close();
	    reader.close();
	} catch(IOException e){ 
	    System.out.println("ERROR: " + e);
	}

	//for(int j=256; j<string_table.size() ; j++){
	System.out.println("\t"+string_table.size());
	//}
	

    } // end compress
	
    // decompression routine
    public void decompress(){
	int MAX_VALUE = 4000; 
	// once we get to here we are going
	// to have to flush the table

	try{
	    reader = new BitStreamInputStream(new BufferedInputStream(new FileInputStream(outFile)), 12);
	    writer = new BitStreamOutputStream(new FileOutputStream(outFile+".DEC"));
	} catch (FileNotFoundException e) {
	    System.out.println("flying pigs in space!!!!!!!!!!"+e);
	}

	Vector string_table = new Vector();

	for(int i=0; i<256; i++){
	    string_table.add(String.valueOf((char)i));
	}

	System.out.println("I am now expanding...");
	int oldCode = 0, newCode = 0;


	try{

	    String aString = "", aChar = "";

	    oldCode = (int)reader.readBitField();
	    aChar = String.valueOf((char)oldCode);

	    writer.write(oldCode);  // looks like it should be aChar.. but done with oldCode??
	    
	    // loop through the rest of the characters
	    while((newCode=(int)reader.readBitField())!=-1) {
	    
		if(newCode >= string_table.size()){
		    aString = (String)string_table.get(oldCode);
		    aString = aString + aChar;
		} else aString = (String)string_table.get(newCode);

		//System.out.print(aString.getBytes());
		writer.write(aString.getBytes());
		aChar = aString.substring(0,1);
		string_table.add((String)string_table.get(oldCode)+aChar);
		oldCode = newCode;

		if(string_table.size()>MAX_VALUE){
		    string_table.removeAllElements();	
		    for(int i=0; i<256; i++){
			string_table.add(String.valueOf((char)i));
		    }
		}
	
	    } // end while
	    reader.close();
	} catch(IOException e){ 
	    System.out.println("ERROR: " + e);
	}

	//for(int j=256; j<string_table.size() ; j++){
	//  System.out.println(j+"\t"+string_table.elementAt(j));
	//}
	
    }// end decompress
	
} // end App
