/*
 * 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.sling.models.impl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.apache.sling.models.factory.MissingElementsException;
import org.apache.sling.models.impl.injectors.ChildResourceInjector;
import org.apache.sling.models.impl.injectors.ValueMapInjector;
import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessorFactory;
import org.apache.sling.models.testmodels.classes.ArrayPrimitivesModel;
import org.apache.sling.models.testmodels.classes.ArrayWrappersModel;
import org.apache.sling.models.testmodels.classes.ChildModel;
import org.apache.sling.models.testmodels.classes.ChildResourceModel;
import org.apache.sling.models.testmodels.classes.ChildValueMapModel;
import org.apache.sling.models.testmodels.classes.ListModel;
import org.apache.sling.models.testmodels.classes.ParentModel;
import org.apache.sling.models.testmodels.classes.ResourceModelWithRequiredField;
import org.apache.sling.models.testmodels.classes.ResourceModelWithRequiredFieldOptionalStrategy;
import org.apache.sling.models.testmodels.classes.SimplePropertyModel;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

@SuppressWarnings("deprecation")
@RunWith(MockitoJUnitRunner.class)
public class ResourceModelClassesTest {

    private ModelAdapterFactory factory;

    @Before
    public void setup() {
        factory = AdapterFactoryTest.createModelAdapterFactory();
        ValueMapInjector valueMapInjector = new ValueMapInjector();
        factory.bindInjector(valueMapInjector, new ServicePropertiesMap(2, 2));
        factory.bindInjector(new ChildResourceInjector(), new ServicePropertiesMap(1, 1));

        factory.injectAnnotationProcessorFactories = factory.injectAnnotationProcessorFactories = Collections.<InjectAnnotationProcessorFactory>singletonList(new ValueMapInjector());
        factory.adapterImplementations.addClassesAsAdapterAndImplementation(SimplePropertyModel.class, ArrayWrappersModel.class, ResourceModelWithRequiredField.class, ChildValueMapModel.class, ArrayPrimitivesModel.class, ChildResourceModel.class, ResourceModelWithRequiredFieldOptionalStrategy.class, ParentModel.class, ChildModel.class, ListModel.class);
    }

    @Test
    public void testSimplePropertyModel() {
        Map<String, Object> map = new HashMap<>();
        map.put("first", "first-value");
        map.put("third", "third-value");
        map.put("intProperty", new Integer(3));
        map.put("arrayProperty", new String[] { "three", "four" });
        ValueMap vm = new ValueMapDecorator(map);

        Resource res = mock(Resource.class);
        when(res.adaptTo(ValueMap.class)).thenReturn(vm);

        SimplePropertyModel model = factory.getAdapter(res, SimplePropertyModel.class);
        assertNotNull(model);
        assertEquals("first-value", model.getFirst());
        assertNull(model.getSecond());
        assertEquals("third-value", model.getThirdProperty());
        assertEquals(3, model.getIntProperty());

        String[] array = model.getArrayProperty();
        assertEquals(2, array.length);
        assertEquals("three", array[0]);

        assertTrue(model.isPostConstructCalled());

        verify(res, times(1)).adaptTo(ValueMap.class);
    }

    @Test
    public void testArrayPrimitivesModel() {
        Map<String, Object> map = new HashMap<>();
        map.put("intArray", new int[] { 1, 2, 9, 8 });
        map.put("secondIntArray", new Integer[] {1, 2, 9, 8});

        ValueMap vm = new ValueMapDecorator(map);
        Resource res = mock(Resource.class);
        when(res.adaptTo(ValueMap.class)).thenReturn(vm);

        ArrayPrimitivesModel model = factory.getAdapter(res, ArrayPrimitivesModel.class);
        assertNotNull(model);

        int[] primitiveIntArray = model.getIntArray();
        assertEquals(4, primitiveIntArray.length);
        assertEquals(2, primitiveIntArray[1]);

        int[] secondPrimitiveIntArray = model.getSecondIntArray();
        assertEquals(4, secondPrimitiveIntArray.length);
        assertEquals(2, secondPrimitiveIntArray[1]);
    }

    @Test
    public void testArrayWrappersModel() {
        Map<String, Object> map = new HashMap<>();
        map.put("intArray", new Integer[] {1, 2, 9, 8});
        map.put("secondIntArray", new int[] {1, 2, 9, 8});

        ValueMap vm = new ValueMapDecorator(map);
        Resource res = mock(Resource.class);
        when(res.adaptTo(ValueMap.class)).thenReturn(vm);

        ArrayWrappersModel model = factory.getAdapter(res, ArrayWrappersModel.class);
        assertNotNull(model);

        Integer[] intArray = model.getIntArray();
        assertEquals(4, intArray.length);
        assertEquals(new Integer(2), intArray[1]);

        Integer[] secondIntArray = model.getSecondIntArray();
        assertEquals(4, secondIntArray.length);
        assertEquals(new Integer(2), secondIntArray[1]);
    }

    @Test
    public void testListModel() {
        Map<String, Object> map = new HashMap<>();
        map.put("intList", new Integer[] {1, 2, 9, 8});
        map.put("stringList", new String[] {"hello", "world"});

        ValueMap vm = new ValueMapDecorator(map);
        Resource res = mock(Resource.class);
        when(res.adaptTo(ValueMap.class)).thenReturn(vm);

        ListModel model = factory.getAdapter(res, ListModel.class);
        assertNotNull(model);

        assertEquals(4, model.getIntList().size());
        assertEquals(new Integer(2), model.getIntList().get(1));

        assertEquals(2, model.getStringList().size());
        assertEquals("hello", model.getStringList().get(0));
    }

    @SuppressWarnings({ "unused", "null" })
    @Test
    public void testRequiredPropertyModel() {
        Map<String, Object> map = new HashMap<>();
        map.put("first", "first-value");
        map.put("third", "third-value");
        ValueMap vm = spy(new ValueMapDecorator(map));

        Resource res = mock(Resource.class);
        when(res.adaptTo(ValueMap.class)).thenReturn(vm);

        ResourceModelWithRequiredField model = factory.getAdapter(res, ResourceModelWithRequiredField.class);
        assertNull(model);

        verify(vm).get("required", String.class);
    }

    @Test
    public void testRequiredPropertyModelWithException() {
        Map<String, Object> map = new HashMap<>();
        map.put("first", "first-value");
        map.put("third", "third-value");
        ValueMap vm = spy(new ValueMapDecorator(map));

        Resource res = mock(Resource.class);
        when(res.adaptTo(ValueMap.class)).thenReturn(vm);

        boolean thrown = false;
        try {
            factory.createModel(res, ResourceModelWithRequiredField.class);
        } catch (MissingElementsException e) {
            assertEquals("required", ((Field) e.getMissingElements().iterator().next().getElement()).getName());
            thrown = true;
        }
        assertTrue(thrown);

        verify(vm).get("required", String.class);
    }

    @SuppressWarnings({ "unused", "null" })
    @Test
    public void testRequiredPropertyMissingModelOptionalStrategy() {
        Map<String, Object> map = new HashMap<>();
        map.put("first", "first-value");
        ValueMap vm = spy(new ValueMapDecorator(map));

        Resource res = mock(Resource.class);
        when(res.adaptTo(ValueMap.class)).thenReturn(vm);

        ResourceModelWithRequiredFieldOptionalStrategy model = factory.getAdapter(res, ResourceModelWithRequiredFieldOptionalStrategy.class);
        assertNull(model);

        verify(vm).get("optional1", String.class);
        verify(vm).get("required1", String.class);
    }

    @Test
    public void testRequiredPropertyModelOptionalStrategy() {
        Map<String, Object> map = new HashMap<>();
        map.put("required1", "required value");
        map.put("required2", "required value");
        map.put("required3", "required value");
        ValueMap vm = spy(new ValueMapDecorator(map));

        Resource res = mock(Resource.class);
        when(res.adaptTo(ValueMap.class)).thenReturn(vm);

        ResourceModelWithRequiredFieldOptionalStrategy model = factory.getAdapter(res, ResourceModelWithRequiredFieldOptionalStrategy.class);
        assertNotNull(model);
        assertEquals("required value", model.getRequired1());
        assertEquals("required value", model.getRequired2());

        verify(vm).get("optional1", String.class);
        verify(vm).get("required1", String.class);
    }

    @Test
    public void testChildResource() {
        Resource child = mock(Resource.class);
        Resource secondChild = mock(Resource.class);
        Resource emptyChild = mock(Resource.class);

        Resource firstGrandChild = mock(Resource.class);
        Resource secondGrandChild = mock(Resource.class);
        when(secondChild.listChildren()).thenReturn(Arrays.asList(firstGrandChild, secondGrandChild).iterator());
        when(emptyChild.listChildren()).thenReturn(Collections.<Resource>emptySet().iterator());

        Resource res = mock(Resource.class);
        when(res.getChild("firstChild")).thenReturn(child);
        when(res.getChild("secondChild")).thenReturn(secondChild);
        when(res.getChild("emptyChild")).thenReturn(emptyChild);

        ChildResourceModel model = factory.getAdapter(res, ChildResourceModel.class);
        assertNotNull(model);
        assertEquals(child, model.getFirstChild());
        assertEquals(2, model.getGrandChildren().size());
        assertEquals(firstGrandChild, model.getGrandChildren().get(0));
        assertEquals(secondGrandChild, model.getGrandChildren().get(1));
        assertEquals(0, model.getEmptyGrandChildren().size());
    }

    @Test
    public void testChildValueMap() {
        ValueMap map = ValueMapDecorator.EMPTY;

        Resource child = mock(Resource.class);
        when(child.adaptTo(ValueMap.class)).thenReturn(map);

        Resource res = mock(Resource.class);
        when(res.getChild("firstChild")).thenReturn(child);

        ChildValueMapModel model = factory.getAdapter(res, ChildValueMapModel.class);
        assertNotNull(model);
        assertEquals(map, model.getFirstChild());
    }

    @Test
    public void testChildModel() {
        Object firstValue = RandomStringUtils.randomAlphabetic(10);
        ValueMap firstMap = new ValueMapDecorator(Collections.singletonMap("property", firstValue));

        final Resource firstChild = mock(Resource.class);
        lenient().when(firstChild.adaptTo(ValueMap.class)).thenReturn(firstMap);
        lenient().when(firstChild.adaptTo(ChildModel.class)).thenAnswer(new AdaptToChildModel());

        Object firstGrandChildValue = RandomStringUtils.randomAlphabetic(10);
        ValueMap firstGrandChildMap = new ValueMapDecorator(Collections.singletonMap("property", firstGrandChildValue));
        Object secondGrandChildValue = RandomStringUtils.randomAlphabetic(10);
        ValueMap secondGrandChildMap = new ValueMapDecorator(Collections.singletonMap("property", secondGrandChildValue));

        final Resource firstGrandChild = mock(Resource.class);
        lenient().when(firstGrandChild.adaptTo(ValueMap.class)).thenReturn(firstGrandChildMap);
        lenient().when(firstGrandChild.adaptTo(ChildModel.class)).thenAnswer(new AdaptToChildModel());

        final Resource secondGrandChild = mock(Resource.class);
        lenient().when(secondGrandChild.adaptTo(ValueMap.class)).thenReturn(secondGrandChildMap);
        lenient().when(secondGrandChild.adaptTo(ChildModel.class)).thenAnswer(new AdaptToChildModel());

        Resource secondChild = mock(Resource.class);
        lenient().when(secondChild.listChildren()).thenReturn(Arrays.asList(firstGrandChild, secondGrandChild).iterator());

        Resource emptyChild = mock(Resource.class);
        lenient().when(emptyChild.listChildren()).thenReturn(Collections.<Resource>emptySet().iterator());

        Resource res = mock(Resource.class);
        lenient().when(res.getChild("firstChild")).thenReturn(firstChild);
        lenient().when(res.getChild("secondChild")).thenReturn(secondChild);
        lenient().when(res.getChild("emptyChild")).thenReturn(emptyChild);

        ParentModel model = factory.getAdapter(res, ParentModel.class);
        assertNotNull(model);

        ChildModel childModel = model.getFirstChild();
        assertNotNull(childModel);
        assertEquals(firstValue, childModel.getProperty());
        assertEquals(2, model.getGrandChildren().size());
        assertEquals(firstGrandChildValue, model.getGrandChildren().get(0).getProperty());
        assertEquals(secondGrandChildValue, model.getGrandChildren().get(1).getProperty());
        assertEquals(0, model.getEmptyGrandChildren().size());
    }

    private class AdaptToChildModel implements Answer<ChildModel> {

        @Override
        public ChildModel answer(InvocationOnMock invocation) throws Throwable {
            return factory.getAdapter(invocation.getMock(), ChildModel.class);
        }
    }

}
