/*
 * 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.api.java.type.lambdas;

import org.apache.flink.api.common.functions.CoGroupFunction;
import org.apache.flink.api.common.functions.CrossFunction;
import org.apache.flink.api.common.functions.FlatJoinFunction;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.GroupReduceFunction;
import org.apache.flink.api.common.functions.InvalidTypesException;
import org.apache.flink.api.common.functions.JoinFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.functions.MapPartitionFunction;
import org.apache.flink.api.common.functions.Partitioner;
import org.apache.flink.api.common.functions.RichMapFunction;
import org.apache.flink.api.common.typeinfo.BasicTypeInfo;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple1;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.typeutils.MissingTypeInfo;
import org.apache.flink.api.java.typeutils.TupleTypeInfo;
import org.apache.flink.api.java.typeutils.TypeExtractionUtils;
import org.apache.flink.api.java.typeutils.TypeExtractor;
import org.apache.flink.api.java.typeutils.TypeInfoParser;

import org.junit.Assert;
import org.junit.Test;

import java.lang.reflect.Method;

import static org.apache.flink.api.java.typeutils.TypeExtractionUtils.checkAndExtractLambda;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

/**
 * Tests the type extractor for lambda functions.
 */
@SuppressWarnings("serial")
public class LambdaExtractionTest {

	@Test
	public void testIdentifyLambdas() {
		try {
			MapFunction<?, ?> anonymousFromInterface = new MapFunction<String, Integer>() {
				@Override
				public Integer map(String value) {
					return Integer.parseInt(value);
				}
			};

			MapFunction<?, ?> anonymousFromClass = new RichMapFunction<String, Integer>() {
				@Override
				public Integer map(String value) {
					return Integer.parseInt(value);
				}
			};

			MapFunction<?, ?> fromProperClass = new StaticMapper();

			MapFunction<?, ?> fromDerived = new ToTuple<Integer>() {
				@Override
				public Tuple2<Integer, Long> map(Integer value) {
					return new Tuple2<>(value, 1L);
				}
			};

			MapFunction<String, Integer> staticLambda = Integer::parseInt;
			MapFunction<Integer, String> instanceLambda = Object::toString;
			MapFunction<String, Integer> constructorLambda = Integer::new;

			assertNull(checkAndExtractLambda(anonymousFromInterface));
			assertNull(checkAndExtractLambda(anonymousFromClass));
			assertNull(checkAndExtractLambda(fromProperClass));
			assertNull(checkAndExtractLambda(fromDerived));
			assertNotNull(checkAndExtractLambda(staticLambda));
			assertNotNull(checkAndExtractLambda(instanceLambda));
			assertNotNull(checkAndExtractLambda(constructorLambda));
			assertNotNull(checkAndExtractLambda(STATIC_LAMBDA));
		}
		catch (Exception e) {
			e.printStackTrace();
			fail(e.getMessage());
		}
	}

	private static class StaticMapper implements MapFunction<String, Integer> {
		@Override
		public Integer map(String value) {
			return Integer.parseInt(value);
		}
	}

	private interface ToTuple<T> extends MapFunction<T, Tuple2<T, Long>> {
		@Override
		Tuple2<T, Long> map(T value) throws Exception;
	}

	private static final MapFunction<String, Integer> STATIC_LAMBDA = Integer::parseInt;

	private static class MyClass {
		private String s = "mystring";

		public MapFunction<Integer, String> getMapFunction() {
			return (i) -> s;
		}
	}

	@Test
	public void testLambdaWithMemberVariable() {
		TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(new MyClass().getMapFunction(), TypeInfoParser.parse("Integer"));
		Assert.assertEquals(ti, BasicTypeInfo.STRING_TYPE_INFO);
	}

	@Test
	public void testLambdaWithLocalVariable() {
		String s = "mystring";
		final int k = 24;
		int j = 26;

		MapFunction<Integer, String> f = (i) -> s + k + j;

		TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, TypeInfoParser.parse("Integer"));
		Assert.assertEquals(ti, BasicTypeInfo.STRING_TYPE_INFO);
	}

	@Test
	public void testMapLambda() {
		MapFunction<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, String>> f = (i) -> null;

		TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@Test
	public void testFlatMapLambda() {
		FlatMapFunction<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, String>> f = (i, o) -> {};

		TypeInformation<?> ti = TypeExtractor.getFlatMapReturnTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@Test
	public void testMapPartitionLambda() {
		MapPartitionFunction<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, String>> f = (i, o) -> {};

		TypeInformation<?> ti = TypeExtractor.getMapPartitionReturnTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@Test
	public void testGroupReduceLambda() {
		GroupReduceFunction<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, String>> f = (i, o) -> {};

		TypeInformation<?> ti = TypeExtractor.getGroupReduceReturnTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@Test
	public void testFlatJoinLambda() {
		FlatJoinFunction<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, Double>, Tuple2<Tuple1<Integer>, String>> f = (i1, i2, o) -> {};

		TypeInformation<?> ti = TypeExtractor.getFlatJoinReturnTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"), TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Double>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@Test
	public void testJoinLambda() {
		JoinFunction<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, Double>, Tuple2<Tuple1<Integer>, String>> f = (i1, i2) -> null;

		TypeInformation<?> ti = TypeExtractor.getJoinReturnTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"), TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Double>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@Test
	public void testCoGroupLambda() {
		CoGroupFunction<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, Double>, Tuple2<Tuple1<Integer>, String>> f = (i1, i2, o) -> {};

		TypeInformation<?> ti = TypeExtractor.getCoGroupReturnTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"), TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Double>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@Test
	public void testCrossLambda() {
		CrossFunction<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, Double>, Tuple2<Tuple1<Integer>, String>> f = (i1, i2) -> null;

		TypeInformation<?> ti = TypeExtractor.getCrossReturnTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"), TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Double>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@Test
	public void testKeySelectorLambda() {
		KeySelector<Tuple2<Tuple1<Integer>, Boolean>, Tuple2<Tuple1<Integer>, String>> f = (i) -> null;

		TypeInformation<?> ti = TypeExtractor.getKeySelectorTypes(f, TypeInfoParser.parse("Tuple2<Tuple1<Integer>, Boolean>"));
		if (!(ti instanceof MissingTypeInfo)) {
			Assert.assertTrue(ti.isTupleType());
			Assert.assertEquals(2, ti.getArity());
			Assert.assertTrue(((TupleTypeInfo<?>) ti).getTypeAt(0).isTupleType());
			Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);
		}
	}

	@SuppressWarnings("rawtypes")
	@Test
	public void testLambdaTypeErasure() {
		MapFunction<Tuple1, Tuple1> f = (i) -> null;
		TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, TypeInfoParser.parse("Tuple1<String>"), null, true);
		Assert.assertTrue(ti instanceof MissingTypeInfo);
	}

	@Test
	public void testPartitionerLambda() {
		Partitioner<Tuple2<Integer, String>> partitioner = (key, numPartitions) -> key.f1.length() % numPartitions;
		final TypeInformation<?> ti = TypeExtractor.getPartitionerTypes(partitioner);

		Assert.assertTrue(ti.isTupleType());
		Assert.assertEquals(2, ti.getArity());
		Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(0), BasicTypeInfo.INT_TYPE_INFO);
		Assert.assertEquals(((TupleTypeInfo<?>) ti).getTypeAt(1), BasicTypeInfo.STRING_TYPE_INFO);

	}

	private static class MyType {
		private int key;

		public int getKey() {
			return key;
		}

		public void setKey(int key) {
			this.key = key;
		}

		protected int getKey2() {
			return 0;
		}
	}

	@Test
	public void testInstanceMethodRefSameType() {
		MapFunction<MyType, Integer> f = MyType::getKey;
		TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, TypeExtractor.createTypeInfo(MyType.class));
		Assert.assertEquals(BasicTypeInfo.INT_TYPE_INFO, ti);
	}

	@Test
	public void testInstanceMethodRefSuperType() {
		MapFunction<Integer, String> f = Object::toString;
		TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, BasicTypeInfo.INT_TYPE_INFO);
		Assert.assertEquals(BasicTypeInfo.STRING_TYPE_INFO, ti);
	}

	private static class MySubtype extends MyType {
		public boolean test;
	}

	@Test
	public void testInstanceMethodRefSuperTypeProtected() {
		MapFunction<MySubtype, Integer> f = MyType::getKey2;
		TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, TypeExtractor.createTypeInfo(MySubtype.class));
		Assert.assertEquals(BasicTypeInfo.INT_TYPE_INFO, ti);
	}

	@Test
	public void testConstructorMethodRef() {
		MapFunction<String, Integer> f = Integer::new;
		TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, BasicTypeInfo.STRING_TYPE_INFO);
		Assert.assertEquals(BasicTypeInfo.INT_TYPE_INFO, ti);
	}

	private interface InterfaceWithDefaultMethod {
		void samMethod();

		default void defaultMethod() {

		}
	}

	@Test
	public void testSamMethodExtractionInterfaceWithDefaultMethod() {
		final Method sam = TypeExtractionUtils.getSingleAbstractMethod(InterfaceWithDefaultMethod.class);
		assertNotNull(sam);
		assertEquals("samMethod", sam.getName());
	}

	private interface InterfaceWithMultipleMethods {
		void firstMethod();

		void secondMethod();
	}

	@Test(expected = InvalidTypesException.class)
	public void getSingleAbstractMethodMultipleMethods() throws Exception {
		TypeExtractionUtils.getSingleAbstractMethod(InterfaceWithMultipleMethods.class);
	}

	private interface InterfaceWithoutAbstractMethod {
		default void defaultMethod() {

		}
	}

	@Test(expected = InvalidTypesException.class)
	public void getSingleAbstractMethodNoAbstractMethods() throws Exception {
		TypeExtractionUtils.getSingleAbstractMethod(InterfaceWithoutAbstractMethod.class);
	}

	private abstract class AbstractClassWithSingleAbstractMethod {
		public abstract void defaultMethod();
	}

	@Test(expected = InvalidTypesException.class)
	public void getSingleAbstractMethodNotAnInterface() throws Exception {
		TypeExtractionUtils.getSingleAbstractMethod(AbstractClassWithSingleAbstractMethod.class);
	}

}
