/*
 * Copyright (c) 2014 Oculus Info Inc.
 * http://www.oculusinfo.com/
 *
 * Released under the MIT License.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.oculusinfo.binning.io.impl;

import com.oculusinfo.binning.TileData;
import com.oculusinfo.binning.TileIndex;
import com.oculusinfo.binning.io.PyramidIO;
import com.oculusinfo.binning.io.serialization.TileSerializer;
import com.oculusinfo.binning.io.serialization.impl.PrimitiveAvroSerializer;

import org.apache.avro.file.CodecFactory;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


public class FileSystemPyramidSourceTest {
	
	private static String SOURCE_DIR = "./src/test/file_pyramid/";
	private static String SOURCE_EXT = "avro";



	@Test 
	public void writeReadAvroRoundTripTest () {
		FileBasedPyramidIO io = new FileBasedPyramidIO(new FileSystemPyramidSource(SOURCE_DIR, SOURCE_EXT));
		TileSerializer<Integer> serializer = new PrimitiveAvroSerializer<>(Integer.class, CodecFactory.nullCodec());

		ArrayList<TileData<Integer>> writeTiles = new ArrayList<TileData<Integer>>();

		TileIndex index = new TileIndex(4, 3, 2);
		TileData<Integer> tile = new TileData<Integer>(index);
		for (int x=0; x<256; ++x) {
			for (int y=0; y<256; ++y) {
				tile.setBin(x, y, x+256*y);
			}
		}
		writeTiles.add(tile);
		writeAvroTiles(io, serializer, "test", writeTiles);

		List<TileData<Integer>> readTiles = readAvroTiles(io, serializer, "test");

		for (int i=0; i<writeTiles.size(); i++){
			TileData<Integer> writeTile = writeTiles.get(i);
			TileIndex writeTileDef = writeTile.getDefinition();
			List<Integer> writeTileData = writeTile.getData();

			TileData<Integer> readTile = readTiles.get(i);
			TileIndex readTileDef = readTile.getDefinition();
			List<Integer> readTileData = readTile.getData();

			Assert.assertEquals(readTileData.size(), writeTileData.size());

			for (int j=0; j<readTileData.size(); j++){
				Assert.assertEquals(readTileData.get(j), writeTileData.get(j));
			}

			Assert.assertEquals(writeTileDef, readTileDef);
		}
	}

	private <T> void writeAvroTiles (PyramidIO pio, TileSerializer<T> serializer,
            							String pyramidId, ArrayList<TileData<T>> tiles) {
		try {
			pio.initializeForWrite(pyramidId);
			pio.writeTiles(pyramidId, serializer, tiles);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private <T> List<TileData<T>> readAvroTiles (PyramidIO pio, TileSerializer<T> serializer, String pyramidId) {
		ArrayList<TileIndex> tiles = new ArrayList<TileIndex>();
		TileIndex index = new TileIndex(4, 3, 2);

		tiles.add(index);
		
		try {
			return pio.readTiles(pyramidId, serializer, tiles);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

}

@@ -1531,16 +1531,80 @@
 actory;%0A
+import org.apache.commons.io.FileUtils;%0Aimport org.junit.After;%0A
 import o
@@ -1644,16 +1644,37 @@
 .Test;%0A%0A
+import java.io.File;%0A
 import j
@@ -1899,16 +1899,158 @@
 %22avro%22;%0A
+%09private static String SOURCE_LAYER = %22test%22;%0A%09private static int LEVEL = 4;%0A%09private static int X_INDEX = 3;%0A%09private static int Y_INDEX = 2;
 %0A%0A%0A%09@Tes
@@ -2370,33 +2370,16 @@
 rayList%3C
-TileData%3CInteger%3E
 %3E();%0A%0A%09%09
@@ -2410,23 +2410,41 @@
 leIndex(
-4, 3, 2
+ LEVEL, X_INDEX, Y_INDEX 
 );%0A%09%09Til
@@ -2478,23 +2478,16 @@
 ileData%3C
-Integer
 %3E(index)
@@ -2647,22 +2647,28 @@
 alizer, 
-%22test%22
+SOURCE_LAYER
 , writeT
@@ -2743,22 +2743,28 @@
 alizer, 
-%22test%22
+SOURCE_LAYER
 );%0A%0A%09%09fo
@@ -3359,32 +3359,230 @@
 leDef);%0A%09%09%7D%0A%09%7D%0A%0A
+%09@After%0A%09public void removeWrittenFile() %7B%0A%09%09try %7B%0A            FileUtils.deleteDirectory(  new File( SOURCE_DIR ) );%0A        %7D catch ( Exception e ) %7B%0A            // swallow exception%0A        %7D%0A%09%7D%0A%0A
 %09private %3CT%3E voi

Clean up test file after test runs.