/*
 * 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.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.sling.api.SlingHttpServletRequest;
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.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.export.spi.ModelExporter;
import org.apache.sling.models.factory.ExportException;
import org.apache.sling.models.factory.InvalidAdaptableException;
import org.apache.sling.models.factory.MissingElementsException;
import org.apache.sling.models.factory.MissingExporterException;
import org.apache.sling.models.factory.ModelClassException;
import org.apache.sling.models.impl.injectors.SelfInjector;
import org.apache.sling.models.impl.injectors.ValueMapInjector;
import org.apache.sling.models.testmodels.classes.CachedModelWithSelfReference;
import org.apache.sling.models.testmodels.classes.ConstructorWithExceptionModel;
import org.apache.sling.models.testmodels.classes.DefaultStringModel;
import org.apache.sling.models.testmodels.classes.InvalidModelWithMissingAnnotation;
import org.apache.sling.models.testmodels.classes.ResourceModelWithRequiredField;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.osgi.util.converter.Converter;
import org.osgi.util.converter.Converters;

@RunWith(MockitoJUnitRunner.class)
public class AdapterFactoryTest {

    @Mock
    private Resource resource;

    @Mock
    private SlingHttpServletRequest request;

    private ModelAdapterFactory factory;

    public static ModelAdapterFactory createModelAdapterFactory() {
        BundleContext bundleContext = Mockito.mock(BundleContext.class);
        return createModelAdapterFactory(bundleContext);
    }

    public static ModelAdapterFactory createModelAdapterFactory(BundleContext bundleContext) {
        ComponentContext componentCtx = Mockito.mock(ComponentContext.class);
        when(componentCtx.getBundleContext()).thenReturn(bundleContext);

        ModelAdapterFactory factory = new ModelAdapterFactory();
        Converter c = Converters.standardConverter();
        Map<String, String> map = new HashMap<>();
        ModelAdapterFactoryConfiguration config = c.convert(map).to(ModelAdapterFactoryConfiguration.class);
        factory.activate(componentCtx, config);
        factory.injectAnnotationProcessorFactories = Collections.emptyList();
        factory.injectAnnotationProcessorFactories2 = Collections.emptyList();
        return factory;
    }

    @Before
    public void setup() {
        factory = createModelAdapterFactory();
        factory.bindInjector(new ValueMapInjector(), new ServicePropertiesMap(0, 0));
        factory.bindInjector(new SelfInjector(), new ServicePropertiesMap(1, 1));
        factory.modelExporters = Arrays.<ModelExporter>asList(new FirstStringExporter(), new SecondStringExporter(), new FirstIntegerExporter());
        factory.adapterImplementations.addClassesAsAdapterAndImplementation(DefaultStringModel.class, ConstructorWithExceptionModel.class, NestedModel.class, NestedModelWithInvalidAdaptable.class, NestedModelWithInvalidAdaptable2.class, ResourceModelWithRequiredField.class, CachedModelWithSelfReference.class) ;
    }

    @Test
    @SuppressWarnings("deprecation")
    public void testIsModelClass() {
        Assert.assertTrue(factory.isModelClass(resource, DefaultStringModel.class));
        Assert.assertFalse(factory.isModelClass(resource, InvalidModelWithMissingAnnotation.class));
    }

    @Test
    public void testCanCreateFromAdaptable() {
        Assert.assertTrue(factory.canCreateFromAdaptable(resource, DefaultStringModel.class));
        Assert.assertFalse(factory.canCreateFromAdaptable(request, DefaultStringModel.class));
    }

    @Test
    public void testCanCreateFromAdaptableWithInvalidModel() {
        Assert.assertFalse(factory.canCreateFromAdaptable(resource, InvalidModelWithMissingAnnotation.class));
    }

    @Test(expected = ModelClassException.class)
    public void testCreateFromNonModelClass() {
        factory.createModel(resource, InvalidModelWithMissingAnnotation.class);
    }

    @Test(expected = InvalidAdaptableException.class)
    public void testCreateFromInvalidAdaptable() {
        factory.createModel(request, DefaultStringModel.class);
    }

    @Test(expected = RuntimeException.class)
    public void testCreateWithConstructorException() {
        // Internally all exceptions are wrapped within RuntimeExceptions
        factory.createModel(resource, ConstructorWithExceptionModel.class);
    }

    @Model(adaptables = SlingHttpServletRequest.class)
    public static class NestedModelWithInvalidAdaptable {
        @Self
        DefaultStringModel nestedModel;
    }

    @Test(expected = MissingElementsException.class)
    public void testCreatedNestedModelWithInvalidAdaptable() {
        // nested model can only be adapted from another adaptable
        factory.createModel(request, NestedModelWithInvalidAdaptable.class);
    }

    @Model(adaptables = SlingHttpServletRequest.class)
    public static class NestedModelWithInvalidAdaptable2 {
        @Self
        InvalidModelWithMissingAnnotation nestedModel;
    }

    @Test(expected = MissingElementsException.class)
    public void testCreatedNestedModelWithInvalidAdaptable2() {
        // nested model is in fact no valid model
        factory.createModel(request, NestedModelWithInvalidAdaptable2.class);
    }

    @Model(adaptables = Resource.class)
    public static class NestedModel {
        @Self
        ResourceModelWithRequiredField nestedModel;

        public ResourceModelWithRequiredField getNestedModel() {
            return nestedModel;
        }
    }

    @Test
    public void testCreatedNestedModel() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("required", "required");
        ValueMap vm = new ValueMapDecorator(map);
        when(resource.adaptTo(ValueMap.class)).thenReturn(vm);

        NestedModel model = factory.createModel(resource, NestedModel.class);
        Assert.assertNotNull(model);
        Assert.assertEquals("required", model.getNestedModel().getRequired());
    }

    @Test(expected=MissingElementsException.class)
    public void testCreatedNestedModelWithMissingElements() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("invalid", "required");
        ValueMap vm = new ValueMapDecorator(map);
        when(resource.adaptTo(ValueMap.class)).thenReturn(vm);

        factory.createModel(resource, NestedModel.class);
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testSelectExporterByName() throws Exception {
        Result<Object> result = mock(Result.class);
        when(result.wasSuccessful()).thenReturn(true);
        when(result.getValue()).thenReturn(new Object());

        String exported = factory.handleAndExportResult(result, "second", String.class, Collections.<String, String>emptyMap());
        Assert.assertEquals("Export from second", exported);
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testSelectExporterByType() throws Exception {
        Result<Object> result = mock(Result.class);
        when(result.wasSuccessful()).thenReturn(true);
        when(result.getValue()).thenReturn(new Object());

        Integer exported = factory.handleAndExportResult(result, "first", Integer.class, Collections.<String, String>emptyMap());
        Assert.assertEquals(Integer.valueOf(42), exported);
    }

    @Test(expected = MissingExporterException.class)
    @SuppressWarnings("unchecked")
    public void testSelectExporterByNameAndWrongType() throws Exception {
        Result<Object> result = mock(Result.class);
        when(result.wasSuccessful()).thenReturn(true);
        when(result.getValue()).thenReturn(new Object());

        factory.handleAndExportResult(result, "second", Integer.class, Collections.<String, String>emptyMap());
    }

    private static class FirstStringExporter implements ModelExporter {
        @Override
        public boolean isSupported(@NotNull Class<?> aClass) {
            return aClass == String.class;
        }

        @Nullable
        @Override
        @SuppressWarnings("unchecked")
        public <T> T export(@NotNull Object o, @NotNull Class<T> aClass, @NotNull Map<String, String> map) throws ExportException {
            if (aClass == String.class) {
                return (T) "Export from first";
            } else {
                throw new ExportException(String.format("%s is not supported.", aClass));
            }
        }

        @NotNull
        @Override
        public String getName() {
            return "first";
        }
    }

    @SuppressWarnings("unchecked")
    private static class SecondStringExporter implements ModelExporter {
        @Override
        public boolean isSupported(@NotNull Class<?> aClass) {
            return aClass == String.class;
        }

        @Nullable
        @Override
        public <T> T export(@NotNull Object o, @NotNull Class<T> aClass, @NotNull Map<String, String> map) throws ExportException {
            if (aClass == String.class) {
                return (T) "Export from second";
            } else {
                throw new ExportException(String.format("%s is not supported.", aClass));
            }
        }

        @NotNull
        @Override
        public String getName() {
            return "second";
        }
    }

    @SuppressWarnings("unchecked")
    private static class FirstIntegerExporter implements ModelExporter {
        @Override
        public boolean isSupported(@NotNull Class<?> aClass) {
            return aClass == Integer.class;
        }

        @Nullable
        @Override
        public <T> T export(@NotNull Object o, @NotNull Class<T> aClass, @NotNull Map<String, String> map) throws ExportException {
            if (aClass == Integer.class) {
                return (T) Integer.valueOf(42);
            } else {
                throw new ExportException(String.format("%s is not supported.", aClass));
            }
        }

        @NotNull
        @Override
        public String getName() {
            return "first";
        }
    }

    @Test
    public void testCreateCachedModelWillNotCrashTheVMWithOOM() throws Exception {
        /*
         * LOAD_FACTOR is used to ensure the test will try create instances of the model to fill up
         * HEAP_SIZE * LOAD_FACTOR memory. This should be a number > 1.0, to ensure that memory would be
         * exhausted, should this test fail.
         */
        double LOAD_FACTOR = 2.0;
        /*
         * SIZE_OF_LONG is the same as Long.BYTES, in Java 8. When Java 8 source & target are used, this
         * can be removed and replaced with Long.BYTES.
         */
        long SIZE_OF_LONG = 8;
        /*
         * instanceSize is an underestimate of the actual size, based on the number of longs in the array.
         * This works for this test, because we want it to try to OOM the VM, and having more instances is
         * better. The smaller instanceSize is, the more instances we try to create (see the calculation for
         * maxInstances below).
         */
        long instanceSize = SIZE_OF_LONG * CachedModelWithSelfReference.numberOfLongs;
        long maxHeapSize = Runtime.getRuntime().maxMemory();
        long maxInstances = (long) ((maxHeapSize / instanceSize) * LOAD_FACTOR);

        for (long i = 0; i < maxInstances; i++) {
            CachedModelWithSelfReference model =
                    factory.createModel(mock(SlingHttpServletRequest.class), CachedModelWithSelfReference.class);
            for (int j = 0; j < model.longs.length; j++) {
                model.longs[j] = j;
            }
        }
    }
}
