package cs211.hw8.test;

import static org.junit.Assert.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.activation.UnsupportedDataTypeException;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import cs211.hw8.BufferedBitWriter;

public class BufferedBitWriterTest {
	private static final String TMP_WRITE = "hw8_data/tmp_bitwriter_out";
	private File _tmpFile;
	
	/**
	 * Create the tmp file we need for writing.
	 * 
	 * @throws IOException
	 */
	@Before
	public void setup() throws IOException{
		_tmpFile = new File(TMP_WRITE);
		
		_tmpFile.createNewFile();
	}
	
	/**
	 * Delete the tmp file when we are done.
	 */
	@After
	public void cleanup(){
		_tmpFile.delete();
	}
	
	
	
	/**
	 * This test the basic writing capability of the writer.
	 * 
	 * @throws IOException
	 */
	@Test
	public void testSimpleWrite() throws IOException {

		BufferedBitWriter writer = new BufferedBitWriter(_tmpFile);
		
		writer.write(1);
		writer.write(1);
		writer.write(1);
		writer.write(1);
		
		writer.write(1);
		writer.write(0);
		writer.write(1);
		writer.write(0);
		
		writer.write(0);
		writer.write(0);
		writer.write(1);
		writer.write(1);
		
		writer.write(1);
		writer.write(0);
		writer.write(1);
		writer.write(1);
		
		writer.close();
		
		FileInputStream input = new FileInputStream(_tmpFile);
		assertEquals("File should have two bytes in it", 2, input.available());
		
		byte[] data = new byte[2];
		
		input.read(data);
		input.close();
		
		assertEquals(-6, data[0]);
		assertEquals(59, data[1]);
		
		
	}
	
	/**
	 * This tests how the writer does when the data is not in even bytes.
	 * 
	 * @throws IOException
	 */
	@Test
	public void testByteBoundaryWrite() throws IOException {
		BufferedBitWriter writer = new BufferedBitWriter(_tmpFile);
		
		writer.write(1);
		writer.write(1);
		writer.write(1);
		writer.write(1);
		
		writer.write(1);
		writer.write(0);
		writer.write(1);
		writer.write(0);
		
		writer.write(0);
		writer.write(0);
		writer.write(1);
		writer.write(1);
		
		
		writer.close();
		
		FileInputStream input = new FileInputStream(_tmpFile);
		assertEquals("File should have two bytes in it", 2, input.available());
		
		byte[] data = new byte[2];
		
		input.read(data);
		input.close();
		
		assertEquals(-6, data[0]);
		assertEquals(48, data[1]);
		
		
	}

	/**
	 * This is a test that writes a large amount to the writer, hopefully exceeding its internal buffer.
	 * 
	 * @throws IOException
	 */
	@Test
	public void testLongWrite() throws IOException {
		BufferedBitWriter writer = new BufferedBitWriter(_tmpFile);
	
	
		for (int i = 0; i < 5000 * 8; i++){
			writer.write(1);
		}
		
		writer.close();
		
		FileInputStream input = new FileInputStream(_tmpFile);
		assertEquals("File should have 5000 bytes in it", 5000, input.available());
		
		byte[] data = new byte[5000];
		input.read(data);
		input.close();
		for (byte b : data){
			assertEquals((byte)0xff,b);
		}
	}
	
	/**
	 * This is a test to make sure it throws the right exception when given bad data.
	 * 
	 * @throws IOException
	 */
	@Test(expected=UnsupportedDataTypeException.class)
	public void testBadDataName() throws IOException {
		BufferedBitWriter writer = new BufferedBitWriter(_tmpFile);
		writer.write(2);
	}
	

}