package com.arondor.common.reflection.gwt.client.presenter;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

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

import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import com.arondor.common.reflection.catalog.SimpleAccessibleClassCatalog;
import com.arondor.common.reflection.gwt.client.presenter.ClassTreeNodePresenter.Display;
import com.arondor.common.reflection.gwt.client.testclasses.ParentTestClass;
import com.arondor.common.reflection.gwt.client.testclasses.TestClass;
import com.arondor.common.reflection.gwt.client.testclasses.TestInterface;
import com.arondor.common.reflection.parser.java.JavaAccessibleClassParser;
import com.arondor.common.reflection.parser.java.JavaClassPathAccessibleClassProvider;
import com.arondor.common.reflection.service.DefaultReflectionService;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;

public class TestClassTreeNodePresenter
{
    private MockGWTReflectionServiceAsync rpcService;

    @Before
    public void init()
    {
        DefaultReflectionService reflectionService = new DefaultReflectionService();
        reflectionService.setAccessibleClassCatalog(new SimpleAccessibleClassCatalog());
        reflectionService.setAccessibleClassParser(new JavaAccessibleClassParser());
        JavaClassPathAccessibleClassProvider provider = new JavaClassPathAccessibleClassProvider();
        List<String> packagePrefixes = new ArrayList<String>();
        packagePrefixes.add(ParentTestClass.class.getPackage().getName());
        provider.setPackagePrefixes(packagePrefixes);
        provider.provideClasses(reflectionService.getAccessibleClassCatalog());

        rpcService = new MockGWTReflectionServiceAsync(reflectionService);
    }

    private ClassTreeNodePresenter.Display mockClassTreeNodePresenterDisplay()
    {
        ClassTreeNodePresenter.Display nodeView = mock(ClassTreeNodePresenter.Display.class);
        ImplementingClassPresenter.Display implView = mock(ImplementingClassPresenter.Display.class);
        AccessibleFieldMapPresenter.Display fieldsView = mock(AccessibleFieldMapPresenter.Display.class);

        when(fieldsView.createAccessibleFieldDisplay()).thenAnswer(new Answer<AccessibleFieldPresenter.Display>()
        {
            public com.arondor.common.reflection.gwt.client.presenter.AccessibleFieldPresenter.Display answer(
                    InvocationOnMock invocation) throws Throwable
            {
                return mock(AccessibleFieldPresenter.Display.class);
            }
        });
        when(nodeView.getImplementingClassDisplay()).thenReturn(implView);
        when(nodeView.getFieldMapDisplay()).thenReturn(fieldsView);
        when(nodeView.createChild()).thenAnswer(new Answer<ClassTreeNodePresenter.Display>()
        {

            public Display answer(InvocationOnMock invocation) throws Throwable
            {
                return mockClassTreeNodePresenterDisplay();
            }
        });
        return nodeView;
    }

    @Test
    public void testChangeBaseClassName()
    {
        ClassTreeNodePresenter.Display nodeView = mockClassTreeNodePresenterDisplay();

        final List<ValueChangeHandler<String>> changeHandlers = new ArrayList<ValueChangeHandler<String>>();
        when(nodeView.getImplementingClassDisplay().addValueChangeHandler(any(ValueChangeHandler.class))).then(
                new Answer<HandlerRegistration>()
                {
                    public HandlerRegistration answer(InvocationOnMock invocation) throws Throwable
                    {
                        changeHandlers.add((ValueChangeHandler<String>) invocation.getArguments()[0]);
                        return mock(HandlerRegistration.class);
                    }
                });

        ClassTreeNodePresenter nodePresenter = new ClassTreeNodePresenter(rpcService, TestInterface.class.getName(),
                nodeView);
        assertEquals(TestInterface.class.getName(), nodePresenter.getBaseClassName());
        assertNull(nodePresenter.getImplementClassName());
        verify(nodeView.getImplementingClassDisplay()).setBaseClassName(TestInterface.class.getName());

        ValueChangeEvent<String> valueChangeEvent = mock(ValueChangeEvent.class);
        when(valueChangeEvent.getValue()).thenReturn(TestClass.class.getName());
        for (ValueChangeHandler<String> changeHandler : changeHandlers)
        {
            changeHandler.onValueChange(valueChangeEvent);
        }
        /*
         * We shall not call selectImplementingClass because it's the widget
         * that selected the class
         */
        verify(nodeView.getImplementingClassDisplay(), times(0)).selectImplementingClass(anyString());
        assertEquals(TestClass.class.getName(), nodePresenter.getImplementClassName());
    }
}

@@ -573,24 +573,105 @@
 ng.Answer;%0A%0A
+import com.arondor.common.reflection.bean.config.ObjectConfigurationFactoryBean;%0A
 import com.a
@@ -733,16 +733,16 @@
 atalog;%0A
-
 import c
@@ -1042,24 +1042,173 @@
 tInterface;%0A
+import com.arondor.common.reflection.model.config.ObjectConfiguration;%0Aimport com.arondor.common.reflection.model.config.ObjectConfigurationFactory;%0A
 import com.a
@@ -1652,16 +1652,16 @@
 enter%0A%7B%0A
-
     priv
@@ -1707,16 +1707,104 @@
 rvice;%0A%0A
+    private ObjectConfigurationFactory factory = new ObjectConfigurationFactoryBean();%0A%0A
     @Bef
@@ -5615,11 +5615,998 @@
 );%0A    %7D
+%0A%0A    @Test%0A    public void testChangeBaseClassNameFromObjectConfiguration()%0A    %7B%0A        ClassTreeNodePresenter.Display nodeView = mockClassTreeNodePresenterDisplay();%0A%0A        ClassTreeNodePresenter nodePresenter = new ClassTreeNodePresenter(rpcService, TestInterface.class.getName(),%0A                nodeView);%0A        assertEquals(TestInterface.class.getName(), nodePresenter.getBaseClassName());%0A        assertNull(nodePresenter.getImplementClassName());%0A        verify(nodeView.getImplementingClassDisplay()).setBaseClassName(TestInterface.class.getName());%0A%0A        ObjectConfiguration objectConfiguration = factory.createObjectConfiguration();%0A        objectConfiguration.setClassName(TestClass.class.getName());%0A%0A        nodePresenter.setObjectConfiguration(objectConfiguration);%0A%0A        verify(nodeView.getImplementingClassDisplay(), times(1)).selectImplementingClass(anyString());%0A        assertEquals(TestClass.class.getName(), nodePresenter.getImplementClassName());%0A    %7D
 %0A%7D%0A

Add unit test : loading an ObjectConfiguration