package org.jtwig.integration.expression;

import com.google.common.collect.ImmutableList;
import org.jtwig.JtwigModel;
import org.jtwig.JtwigTemplate;
import org.jtwig.environment.EnvironmentConfiguration;
import org.jtwig.environment.EnvironmentConfigurationBuilder;
import org.jtwig.property.resolver.PropertyResolver;
import org.jtwig.property.selection.cache.SelectionPropertyResolverCacheKey;
import org.jtwig.property.selection.cache.SelectionPropertyResolverPersistentCache;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class PolymorphicVariableTest {

	private List<ParentClass> list;
	private EnvironmentConfiguration configuration;

	private abstract class ParentClass {
		public abstract String getType();
	}

	private class ConcreteClassA extends ParentClass {
		public String getType() {
			return "A";
		}
	}

	private class ConcreteClassB extends ParentClass {
		public String getType() {
			return "B";
		}
	}

	@Before
	public void setupTestInstances() {
		list = ImmutableList.of(
				new ConcreteClassA(),
				new ConcreteClassB(),
				new ConcreteClassA()
		);
	}

	@Before
	public void setupConfiguration() {
		final ConcurrentHashMap<SelectionPropertyResolverCacheKey, PropertyResolver> resolverHashMap = new ConcurrentHashMap<>();
		final SelectionPropertyResolverPersistentCache resolverCache = new SelectionPropertyResolverPersistentCache(resolverHashMap);

		configuration = EnvironmentConfigurationBuilder.configuration()
				.propertyResolver().withCache(resolverCache).and()
				.build();
	}

	@Test
	public void testPolymorphicVariableIsAcceessibleInPresenceOfPersistantResolverCache() {
		String result = JtwigTemplate.inlineTemplate("{% for item in list %}{{ item.type }}{% endfor %}", configuration)
				.render(JtwigModel.newModel().with("list", list));

		assertThat(result, is("ABA"));
	}
}

@@ -729,17 +729,20 @@
 Test %7B%0A%0A
-%09
+    
 private 
@@ -765,17 +765,20 @@
 %3E list;%0A
-%09
+    
 private 
@@ -818,17 +818,20 @@
 ation;%0A%0A
-%09
+    
 private 
@@ -855,26 +855,32 @@
 rentClass %7B%0A
-%09%09
+        
 public abstr
@@ -901,21 +901,27 @@
 Type();%0A
-%09%7D%0A%0A%09
+    %7D%0A%0A    
 private 
@@ -955,34 +955,40 @@
 s ParentClass %7B%0A
-%09%09
+        
 public String ge
@@ -1001,32 +1001,53 @@
 ) %7B%0A
-%09%09%09return %22A%22;%0A%09%09%7D%0A%09%7D%0A%0A%09
+            return %22A%22;%0A        %7D%0A    %7D%0A%0A    
 priv
@@ -1093,18 +1093,24 @@
 Class %7B%0A
-%09%09
+        
 public S
@@ -1131,40 +1131,61 @@
 ) %7B%0A
-%09%09%09return %22B%22;%0A%09%09%7D%0A%09%7D%0A%0A%09
+            return %22B%22;%0A        %7D%0A    %7D%0A%0A    
 @Before%0A
 %09pub
@@ -1172,33 +1172,36 @@
  %7D%0A%0A    @Before%0A
-%09
+    
 public void setu
@@ -1219,18 +1219,24 @@
 ces() %7B%0A
-%09%09
+        
 list = I
@@ -1252,20 +1252,32 @@
 ist.of(%0A
-%09%09%09%09
+                
 new Conc
@@ -1286,28 +1286,40 @@
 teClassA(),%0A
-%09%09%09%09
+                
 new Concrete
@@ -1328,20 +1328,32 @@
 assB(),%0A
-%09%09%09%09
+                
 new Conc
@@ -1369,26 +1369,38 @@
 A()%0A
-%09%09);%0A%09%7D%0A%0A%09
+        );%0A    %7D%0A%0A    
 @Before%0A
 %09pub
@@ -1395,17 +1395,20 @@
 @Before%0A
-%09
+    
 public v
@@ -1434,18 +1434,24 @@
 ion() %7B%0A
-%09%09
+        
 final Co
@@ -1564,18 +1564,24 @@
 ap%3C%3E();%0A
-%09%09
+        
 final Se
@@ -1699,18 +1699,24 @@
 hMap);%0A%0A
-%09%09
+        
 configur
@@ -1771,20 +1771,32 @@
 ation()%0A
-%09%09%09%09
+                
 .propert
@@ -1842,34 +1842,55 @@
 d()%0A
-%09%09%09%09.build();%0A%09%7D%0A%0A%09
+                .build();%0A    %7D%0A%0A    
 @Test%0A
-%09
+    
 publ
@@ -1973,18 +1973,24 @@
 che() %7B%0A
-%09%09
+        
 String r
@@ -2098,12 +2098,24 @@
 on)%0A
-%09%09%09%09
+                
 .ren
@@ -2166,10 +2166,16 @@
 );%0A%0A
-%09%09
+        
 asse
@@ -2205,9 +2205,12 @@
 ));%0A
-%09
+    
 %7D%0A%7D%0A

change indentation to match project