/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.flink.types.parser;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.flink.configuration.ConfigConstants;
import org.apache.flink.util.TestLogger;
import org.junit.Test;


/**
 *
 */
public abstract class ParserTestBase<T> extends TestLogger {
	
	public abstract String[] getValidTestValues();
	
	public abstract T[] getValidTestResults();
	
	public abstract String[] getInvalidTestValues();

	public abstract boolean allowsEmptyField();
	
	public abstract FieldParser<T> getParser();
	
	public abstract Class<T> getTypeClass();
	
	@Test
	public void testTest() {
		assertNotNull(getParser());
		assertNotNull(getTypeClass());
		assertNotNull(getValidTestValues());
		assertNotNull(getValidTestResults());
		assertNotNull(getInvalidTestValues());
		assertTrue(getValidTestValues().length == getValidTestResults().length);
	}
	
	@Test
	public void testGetValue() {
		try {
			FieldParser<?> parser = getParser();
			Object created = parser.createValue();
			
			assertNotNull("Null type created", created);
			assertTrue("Wrong type created", getTypeClass().isAssignableFrom(created.getClass()));
		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}
	
	@Test
	public void testValidStringInIsolation() {
		try {
			String[] testValues = getValidTestValues();
			T[] results = getValidTestResults();
			
			for (int i = 0; i < testValues.length; i++) {

				FieldParser<T> parser1 = getParser();
				FieldParser<T> parser2 = getParser();
				FieldParser<T> parser3 = getParser();
				
				byte[] bytes1 = testValues[i].getBytes(ConfigConstants.DEFAULT_CHARSET);
				byte[] bytes2 = testValues[i].getBytes(ConfigConstants.DEFAULT_CHARSET);
				byte[] bytes3 = testValues[i].getBytes(ConfigConstants.DEFAULT_CHARSET);

				int numRead1 = parser1.parseField(bytes1, 0, bytes1.length, new byte[] {'|'}, parser1.createValue());
				int numRead2 = parser2.parseField(bytes2, 0, bytes2.length, new byte[] {'&', '&'}, parser2.createValue());
				int numRead3 = parser3.parseField(bytes3, 0, bytes3.length, new byte[] {'9','9','9'}, parser3.createValue());

				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", numRead1 != -1);
				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", numRead2 != -1);
				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", numRead3 != -1);

				assertEquals("Invalid number of bytes read returned.", bytes1.length, numRead1);
				assertEquals("Invalid number of bytes read returned.", bytes2.length, numRead2);
				assertEquals("Invalid number of bytes read returned.", bytes3.length, numRead3);

				T result1 = parser1.getLastResult();
				T result2 = parser2.getLastResult();
				T result3 = parser3.getLastResult();

				assertEquals("Parser parsed wrong. "+testValues[i], results[i], result1);
				assertEquals("Parser parsed wrong. "+testValues[i], results[i], result2);
				assertEquals("Parser parsed wrong. "+testValues[i], results[i], result3);
			}
			
		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}

	@Test
	public void testValidStringInIsolationWithEndDelimiter() {
		try {
			String[] testValues = getValidTestValues();
			T[] results = getValidTestResults();

			for (int i = 0; i < testValues.length; i++) {

				FieldParser<T> parser1 = getParser();
				FieldParser<T> parser2 = getParser();

				String testVal1 = testValues[i] + "|";
				String testVal2 = testValues[i] + "&&&&";

				byte[] bytes1 = testVal1.getBytes(ConfigConstants.DEFAULT_CHARSET);
				byte[] bytes2 = testVal2.getBytes(ConfigConstants.DEFAULT_CHARSET);

				int numRead1 = parser1.parseField(bytes1, 0, bytes1.length, new byte[] {'|'}, parser1.createValue());
				int numRead2 = parser2.parseField(bytes2, 0, bytes2.length, new byte[] {'&', '&','&', '&'}, parser2.createValue());

				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", numRead1 != -1);
				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", numRead2 != -1);

				assertEquals("Invalid number of bytes read returned.", bytes1.length, numRead1);
				assertEquals("Invalid number of bytes read returned.", bytes2.length, numRead2);

				T result1 = parser1.getLastResult();
				T result2 = parser2.getLastResult();

				assertEquals("Parser parsed wrong.", results[i], result1);
				assertEquals("Parser parsed wrong.", results[i], result2);
			}

		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}
	
	@Test
	public void testConcatenated() {
		try {
			String[] testValues = getValidTestValues();
			T[] results = getValidTestResults();
			byte[] allBytesWithDelimiter = concatenate(testValues, new char[] {'|'}, true);
			byte[] allBytesNoDelimiterEnd = concatenate(testValues, new char[] {','}, false);

			FieldParser<T> parser1 = getParser();
			FieldParser<T> parser2 = getParser();

			T val1 = parser1.createValue();
			T val2 = parser2.createValue();

			int pos1 = 0;
			int pos2 = 0;

			for (int i = 0; i < results.length; i++) {
				pos1 = parser1.parseField(allBytesWithDelimiter, pos1, allBytesWithDelimiter.length, new byte[] {'|'}, val1);
				pos2 = parser2.parseField(allBytesNoDelimiterEnd, pos2, allBytesNoDelimiterEnd.length, new byte[] {','}, val2);

				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", pos1 != -1);
				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", pos2 != -1);

				T result1 = parser1.getLastResult();
				T result2 = parser2.getLastResult();

				assertEquals("Parser parsed wrong.", results[i], result1);
				assertEquals("Parser parsed wrong.", results[i], result2);
			}
		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}

	@Test
	public void testConcatenatedMultiCharDelimiter() {
		try {
			String[] testValues = getValidTestValues();
			T[] results = getValidTestResults();
			byte[] allBytesWithDelimiter = concatenate(testValues, new char[] {'&','&', '&', '&'}, true);
			byte[] allBytesNoDelimiterEnd = concatenate(testValues, new char[] {'9', '9', '9'}, false);

			FieldParser<T> parser1 = getParser();
			FieldParser<T> parser2 = getParser();

			T val1 = parser1.createValue();
			T val2 = parser2.createValue();

			int pos1 = 0;
			int pos2 = 0;

			for (int i = 0; i < results.length; i++) {
				pos1 = parser1.parseField(allBytesWithDelimiter, pos1,  allBytesWithDelimiter.length,   new byte[] {'&','&','&','&'}, val1);
				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", pos1 != -1);
				T result1 = parser1.getLastResult();
				assertEquals("Parser parsed wrong.", results[i], result1);

				pos2 = parser2.parseField(allBytesNoDelimiterEnd, pos2, allBytesNoDelimiterEnd.length,  new byte[] {'9','9','9'}, val2);
				assertTrue("Parser declared the valid value " + testValues[i] + " as invalid.", pos2 != -1);
				T result2 = parser2.getLastResult();
				assertEquals("Parser parsed wrong.", results[i], result2);

			}
		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}
	
	@Test
	public void testInValidStringInIsolation() {
		try {
			String[] testValues = getInvalidTestValues();
			
			for (int i = 0; i < testValues.length; i++) {
				
				FieldParser<T> parser = getParser();
				
				byte[] bytes = testValues[i].getBytes(ConfigConstants.DEFAULT_CHARSET);
				int numRead = parser.parseField(bytes, 0, bytes.length, new byte[]{'|'}, parser.createValue());
				
				assertTrue("Parser accepted the invalid value " + testValues[i] + ".", numRead == -1);
			}
		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}
	
	@Test
	public void testInValidStringsMixedIn() {
		try {
			String[] validValues = getValidTestValues();
			T[] validResults = getValidTestResults();
			
			String[] invalidTestValues = getInvalidTestValues();
			
			FieldParser<T> parser = getParser();
			T value = parser.createValue();
			
			
			for (String invalid : invalidTestValues) {
				
				// place an invalid string in the middle
				String[] testLine = new String[validValues.length + 1];
				int splitPoint = validValues.length / 2;
				System.arraycopy(validValues, 0, testLine, 0, splitPoint);
				testLine[splitPoint] = invalid;
				System.arraycopy(validValues, splitPoint, testLine, splitPoint + 1, validValues.length - splitPoint);
				
				byte[] bytes = concatenate(testLine, new char[] {'%'}, true);
				
				// read the valid parts
				int pos = 0;
				for (int i = 0; i < splitPoint; i++) {
					pos = parser.parseField(bytes, pos, bytes.length, new byte[] {'%'}, value);
					
					assertTrue("Parser declared the valid value " + validValues[i] + " as invalid.", pos != -1);
					T result = parser.getLastResult();
					assertEquals("Parser parsed wrong.", validResults[i], result);
				}
				
				// fail on the invalid part
				pos = parser.parseField(bytes, pos, bytes.length, new byte[] {'%'}, value);
				assertTrue("Parser accepted the invalid value " + invalid + ".", pos == -1);
			}
		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}
	
	@Test
	@SuppressWarnings("unchecked")
	public void testStaticParseMethod() {
		try {
			Method parseMethod = null;
			try {
				parseMethod = getParser().getClass().getMethod("parseField", byte[].class, int.class, int.class, char.class);
			}
			catch (NoSuchMethodException e) {
				return;
			}
			
			String[] testValues = getValidTestValues();
			T[] results = getValidTestResults();
			
			for (int i = 0; i < testValues.length; i++) {
				
				byte[] bytes = testValues[i].getBytes(ConfigConstants.DEFAULT_CHARSET);
				
				
				T result;
				try {
					result = (T) parseMethod.invoke(null, bytes, 0, bytes.length, '|');
				}
				catch (InvocationTargetException e) {
					e.getTargetException().printStackTrace();
					fail("Error while parsing: " + e.getTargetException().getMessage());
					return;
				}
				assertEquals("Parser parsed wrong.", results[i], result);
			}
		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}
	
	@Test
	public void testStaticParseMethodWithInvalidValues() {
		try {
			Method parseMethod = null;
			try {
				parseMethod = getParser().getClass().getMethod("parseField", byte[].class, int.class, int.class, char.class);
			}
			catch (NoSuchMethodException e) {
				return;
			}
			
			String[] testValues = getInvalidTestValues();
			
			for (int i = 0; i < testValues.length; i++) {
				
				byte[] bytes = testValues[i].getBytes(ConfigConstants.DEFAULT_CHARSET);
				
				try {
					parseMethod.invoke(null, bytes, 0, bytes.length, '|');
					fail("Static parse method accepted invalid value");
				}
				catch (InvocationTargetException e) {
					// that's it!
				}
			}
		}
		catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}
	
	private static byte[] concatenate(String[] values, char[] delimiter, boolean delimiterAtEnd) {
		int len = 0;
		for (String s : values) {
			len += s.length() + delimiter.length;
		}
		
		if (!delimiterAtEnd) {
			len-=delimiter.length;
		}
		
		int currPos = 0;
		byte[] result = new byte[len];
		
		for (int i = 0; i < values.length; i++) {
			String s = values[i];
			
			byte[] bytes = s.getBytes(ConfigConstants.DEFAULT_CHARSET);
			int numBytes = bytes.length;
			System.arraycopy(bytes, 0, result, currPos, numBytes);
			currPos += numBytes;
			
			if (delimiterAtEnd || i < values.length-1) {
				for(int j = 0; j < delimiter.length; j++)
				result[currPos++] = (byte) delimiter[j];
			}
		}
		
		return result;
	}

	@Test
	public void testTrailingEmptyField() {
		try {
			FieldParser<T> parser = getParser();

			byte[] bytes = "||".getBytes(ConfigConstants.DEFAULT_CHARSET);

			for (int i = 0; i < 2; i++) {

				// test empty field with trailing delimiter when i = 0,
				// test empty field with out trailing delimiter when i= 1.
				int numRead = parser.parseField(bytes, i, bytes.length, new byte[]{'|'}, parser.createValue());

				assertEquals(FieldParser.ParseErrorState.EMPTY_COLUMN, parser.getErrorState());

				if (this.allowsEmptyField()) {
					assertTrue("Parser declared the empty string as invalid.", numRead != -1);
					assertEquals("Invalid number of bytes read returned.", i + 1, numRead);
				} else {
					assertTrue("Parser accepted the empty string.", numRead == -1);
				}

				parser.resetParserState();
			}

		} catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
			fail("Test erroneous: " + e.getMessage());
		}
	}

}
