package cs211.hw8.test;

import static org.junit.Assert.*;

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

import org.junit.Test;

import cs211.hw8.BufferedBitReader;

public class BufferedBitReaderTest {
	// This is the data file that we will use to test the reader functionality. It has 32 bytes in it containing the values
	// 1,2,3,4,...,32
	private static final String DATA_FILE = "hw8_data/assignment8_raw_data_reference";
	
	
	/**
	 * Test the basic read functionality. 
	 * 
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	@Test
	public void testRead() throws FileNotFoundException, IOException {
		BufferedBitReader reader = new BufferedBitReader(new File(DATA_FILE));
		
		for (int b = 1; b <= 32; b++){
			int singleByte = 0;
			for (int i = 0; i < 8; i++){
				singleByte  = (singleByte << 1) | reader.read();
			}
			assertEquals(b, singleByte);
		}
		
	}
	
	
	/**
	 * Test to see if the hasNext function works.
	 * 
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	@Test
	public void testHasNext() throws FileNotFoundException, IOException{
		BufferedBitReader reader = new BufferedBitReader(new File(DATA_FILE));
		
		assertTrue("Should have next at start of file", reader.hasNext());
		
		for (int i = 0; i < (32 * 8) - 1; i++){
			reader.read();
			assertTrue("Should have next after reading bit " + i, reader.hasNext());
		}
		
		reader.read();
		assertFalse("Should have reached the end of the file", reader.hasNext());
	}
	
	/**
	 * Test the skip function.
	 * 
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	@Test
	public void testSkip() throws FileNotFoundException, IOException{
		BufferedBitReader reader = new BufferedBitReader(new File(DATA_FILE));
		
		reader.skip(8);
		int singleByte = 0;
		for (int i = 0; i < 8; i++){
			singleByte  = (singleByte << 1) | reader.read();
		}
		assertEquals(2, singleByte);
		
		reader.skip(4);
		singleByte = 0;
		for (int i = 0; i < 8; i++){
			singleByte  = (singleByte << 1) | reader.read();
		}
		assertEquals(48, singleByte);
		
	}
	
	
	/**
	 * Test the behavior of running off the end of the file.
	 * 
	 * @throws IOException 
	 * @throws FileNotFoundException 
	 */
	@Test(expected=IndexOutOfBoundsException.class)
	public void testOverRead() throws FileNotFoundException, IOException{
		BufferedBitReader reader = new BufferedBitReader(new File(DATA_FILE));
		reader.skip(32 * 8);
		int data = reader.read();
		fail("Expected to run out of data, but got " + data + " instead");
	}
	
	
	/**
	 * Test to see if the reader throws a FileNotFoundException.
	 * 
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	@Test(expected=FileNotFoundException.class)
	public void testFileNotFound() throws FileNotFoundException, IOException {
		BufferedBitReader reader = new BufferedBitReader(new File("bad_file"));
		fail("Should have thrown a FileNotFoundException");
	}

}