/*
 * 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.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.runners.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));
    }

    @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);
    }

    @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);
        when(firstChild.adaptTo(ValueMap.class)).thenReturn(firstMap);
        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);
        when(firstGrandChild.adaptTo(ValueMap.class)).thenReturn(firstGrandChildMap);
        when(firstGrandChild.adaptTo(ChildModel.class)).thenAnswer(new AdaptToChildModel());

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

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

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

        Resource res = mock(Resource.class);
        when(res.getChild("firstChild")).thenReturn(firstChild);
        when(res.getChild("secondChild")).thenReturn(secondChild);
        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);
        }
    }

}
