package coding;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

/**
 * Reads a text document and produces a file with the optimal coding for this
 * document
 * 
 * @author Benjamin Gojman
 */
public class GenerateCode {

	public static boolean IGNORE_MISSIONG = false;
	
	/* if you are using an array implementation, set this to true */
	public static boolean ARRAY_IMPLEMENTATION = false;

	public static void main(String[] args) throws IOException {

		if (args.length != 2) {
			System.out
					.println("Expecting 2 arguments <text file> <code file> but got "
							+ args.length);
			System.exit(0);
		}

		String textFile = args[0];
		String codeFile = args[1];

		FileInputStream fr = new FileInputStream(textFile);
		DataInputStream br = new DataInputStream(fr);
		
		/* Create your data structure for the frequency count
		 * If using an array implementation create the array (freqCountArray) properly below
		 * If using a hashmap use the structure created below
		 */
		int[] freqCountArray = new int[1]; //make sure to modify this if you are using arrays
		
		Map<Integer, Integer> frequencyCount = new HashMap<Integer, Integer>();
		
		int next;
		try {
			while (true) {
				next = br.readUnsignedByte();
				/* Put your frequency counting code in here 
				 * Next is the next byte in the file you are reading
				 */
				
			}
		} catch (EOFException e) {
		}

		
		if(ARRAY_IMPLEMENTATION){
			for(int i = 0; i<freqCountArray.length; i++){
				frequencyCount.put(i,  freqCountArray[i]);
			}
		}

		PriorityQueue<CodeWord> frequencyOrder = new PriorityQueue<CodeWord>();

		for (int i = 0; i < 256; i++) {
			if (frequencyCount.containsKey(i)) {
				int freq = frequencyCount.get(i).intValue();
				frequencyOrder.add(new CodeWord(freq, i));
			} else if (!IGNORE_MISSIONG) {
				frequencyOrder.add(new CodeWord(0, i));

			}
		}

		while (frequencyOrder.size() > 1) {
			CodeWord firstChar = frequencyOrder.poll();
			CodeWord secondChar = frequencyOrder.poll();
			CodeWord join = new CodeWord(firstChar, secondChar);
			frequencyOrder.add(join);
		}

		CodeWord[] finalCode = new CodeWord[256];

		CodeWord root = frequencyOrder.poll();

		root.createCodes("", finalCode);

		for (CodeWord codeWord : finalCode) {
			if (codeWord != null)
				frequencyOrder.add(codeWord);
		}

		PrintWriter pw = new PrintWriter(new File(codeFile));

		for (CodeWord codeWord : finalCode) {
			if (codeWord != null) {
				pw.println(codeWord.character + " " + codeWord.code);
			}
		}

		pw.close();
	}
}

