/*
 * JBoss, Home of Professional Open Source.
 * See the COPYRIGHT.txt file distributed with this work for information
 * regarding copyright ownership.  Some portions may be licensed
 * to Red Hat, Inc. under one or more contributor license agreements.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */

package org.teiid.resource.adapter.google.unit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import junit.framework.Assert;

import org.junit.Test;
import org.teiid.resource.adapter.google.common.SheetRow;
import org.teiid.resource.adapter.google.result.PartialResultExecutor;
import org.teiid.resource.adapter.google.result.RowsResult;


/**
 * This unit test verifies batch behavior and iteration behavior of RowsResult.
 * 
 * @author fnguyen
 *
 */
@SuppressWarnings("nls")
public class RowsResultTest {

	@Test 
	public void simpleIteration(){
		final List<SheetRow> rows = new ArrayList<SheetRow>();
		rows.add(new SheetRow(new String[]{"a","b","c"}));
		rows.add(new SheetRow(new String[]{"a2","b2","c2"}));
		rows.add(new SheetRow(new String[]{"a3","b3","c3"}));
		
		RowsResult result = new RowsResult(new PartialResultExecutor() {
			boolean called = false;
			
			@Override
			public List<SheetRow> getResultsBatch(int startIndex, int endIndex) {
				if (called)
					Assert.fail("getResultsBatch should've been called only once");
				called = true;
				return rows;
			}
		}, 10);
		
		int i = 0;
		for (SheetRow row : result){
			Assert.assertEquals(row, rows.get(i++));
		}
	}
	

	@Test 
	public void twoBatchCallsNeeded(){
		final List<SheetRow> firstPart = new ArrayList<SheetRow>();
		final List<SheetRow> secondPart = new ArrayList<SheetRow>();
		final List<SheetRow> all = new ArrayList<SheetRow>();
		firstPart.add(new SheetRow(new String[]{"a","b","c"}));
		firstPart.add(new SheetRow(new String[]{"a2","b2","c2"}));
		firstPart.add(new SheetRow(new String[]{"a3","b3","c3"}));
		secondPart.add(new SheetRow(new String[]{"a4","b4","c4"}));
		secondPart.add(new SheetRow(new String[]{"a5","b5","c5"}));
		all.addAll(firstPart);
		all.addAll(secondPart);
		
		RowsResult result = new RowsResult(new PartialResultExecutor() {
			int called = 0;
			
			@Override
			public List<SheetRow> getResultsBatch(int startIndex, int endIndex) {
				if (called++ > 2)
					Assert.fail("getResultsBatch at most twice");
				
				if (called == 1){
					return firstPart;
				} else if (called == 2){
					return secondPart;	
				}
				//Shouldn't reach here.
				return null;
			}
		}, 3);
		
		int i = 0;
		for (SheetRow row : result){
			Assert.assertEquals(row, all.get(i++));
		}
		Assert.assertEquals("Six rows should be in the result",5, i);
	}
	

	@Test 
	public void noRows(){
		final List<SheetRow> all = new ArrayList<SheetRow>();

		
		RowsResult result = new RowsResult(new PartialResultExecutor() {
			int called = 0;
			
			@Override
			public List<SheetRow> getResultsBatch(int startIndex, int endIndex) {
				if (called++ > 1)
					Assert.fail("getResultsBatch at once");
				
				return all;
			}
		}, 3);
		
		int i = 0;
		for (SheetRow row : result){
			i++;
		}
		Assert.assertEquals("No iterations should be made",0, i);
	}
	

	@Test 
	public void sixBatchCalls(){
		final List<SheetRow> all = new ArrayList<SheetRow>();
		all.add(new SheetRow(new String[]{"a","b","c"}));
		all.add(new SheetRow(new String[]{"a2","b2","c2"}));
		all.add(new SheetRow(new String[]{"a3","b3","c3"}));
		all.add(new SheetRow(new String[]{"a4","b4","c4"}));
		all.add(new SheetRow(new String[]{"a5","b5","c5"}));
		all.add(new SheetRow(new String[]{"a6","b6","c6"}));
		
		RowsResult result = new RowsResult(new PartialResultExecutor() {
			int called = 0;
			
			@Override
			public List<SheetRow> getResultsBatch(int startIndex, int endIndex) {
				if (called > 6)
					Assert.fail("getResultsBatch at least 6 times");
				
				if (called == 6)
					return new ArrayList<SheetRow>();
				return Collections.singletonList(all.get(called++));
			}
		}, 1);
		
		int i = 0;
		for (SheetRow row : result){
			Assert.assertEquals(all.get(i++), row);
		}
		Assert.assertEquals("Six iterations should be made",6, i);
	}
	
	@Test
	public void offsetTest(){
		final List<SheetRow> all = new ArrayList<SheetRow>();
		all.add(new SheetRow(new String[]{"a","b","c"}));
		all.add(new SheetRow(new String[]{"a2","b2","c2"}));
		all.add(new SheetRow(new String[]{"a3","b3","c3"}));
		all.add(new SheetRow(new String[]{"a4","b4","c4"}));
		all.add(new SheetRow(new String[]{"a5","b5","c5"}));
		all.add(new SheetRow(new String[]{"a6","b6","c6"}));
		
		RowsResult result = new RowsResult(new PartialResultExecutor() {
			int called = 0;
			
			@Override
			public List<SheetRow> getResultsBatch(int startIndex, int endIndex) {
				if (called++ > 1)
					Assert.fail("getResultsBatch at most 2 times");
				
				ArrayList<SheetRow> result = new ArrayList<SheetRow>();
				if (called == 1) {
					result.add(all.get(3));
					result.add(all.get(4));
				} else if (called == 2)
					result.add(all.get(5));
				
				return result;
			}
		}, 2);
		
		result.setOffset(3);
		result.setLimit(3);
		
		int i = 3;
		for (SheetRow row : result){
			Assert.assertEquals(all.get(i++), row);
		}
		Assert.assertEquals("3 iterations should be made",3, i-3);
	}	
	
	@Test
	public void offsetTestOne(){
		final List<SheetRow> all = new ArrayList<SheetRow>();
		all.add(new SheetRow(new String[]{"a","b","c"}));
		all.add(new SheetRow(new String[]{"a2","b2","c2"}));
		all.add(new SheetRow(new String[]{"a3","b3","c3"}));
		all.add(new SheetRow(new String[]{"a4","b4","c4"}));
		all.add(new SheetRow(new String[]{"a5","b5","c5"}));
		all.add(new SheetRow(new String[]{"a6","b6","c6"}));
		
		RowsResult result = new RowsResult(new PartialResultExecutor() {
			int called = 0;
			
			@Override
			public List<SheetRow> getResultsBatch(int startIndex, int endIndex) {
				if (called++ > 2)
					Assert.fail("getResultsBatch at most 3 times");
				
				ArrayList<SheetRow> result = new ArrayList<SheetRow>();
				if (called == 1) {
					result.add(all.get(1));
					result.add(all.get(2));
				} else if (called == 2) {
					result.add(all.get(3));
				    result.add(all.get(4));
				} else if (called == 3)
					result.add(all.get(5));
				return result;
			}
		}, 2);
		
		result.setOffset(1);
		result.setLimit(6);
		
		int i = 1;
		for (SheetRow row : result){
			Assert.assertEquals(all.get(i++), row);
		}
		Assert.assertEquals("5 iterations should be made",5, i-1);
	}
}

