/*
 * 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 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.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.models.annotations.Required;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.factory.MissingElementException;
import org.apache.sling.models.factory.MissingElementsException;
import org.apache.sling.models.impl.injectors.ValueMapInjector;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;

import java.util.Collections;
import java.util.Hashtable;

import static org.mockito.Mockito.when;
import static org.junit.Assert.*;

@RunWith(MockitoJUnitRunner.class)
public class AnnotationConflictsTest {

    @Mock
    private ComponentContext componentCtx;

    @Mock
    private BundleContext bundleContext;

    private ModelAdapterFactory factory;

    @Mock
    private Resource resource;

    @Before
    public void setup() {
        when(componentCtx.getBundleContext()).thenReturn(bundleContext);
        when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>());

        factory = new ModelAdapterFactory();
        factory.activate(componentCtx);
        ValueMapInjector injector = new ValueMapInjector();

        factory.bindInjector(injector, new ServicePropertiesMap(1, 1));
        factory.bindInjectAnnotationProcessorFactory(injector, new ServicePropertiesMap(1, 1));

        for (Class<?> clazz : this.getClass().getDeclaredClasses()) {
            if (!clazz.isInterface()) {
                factory.adapterImplementations.addClassesAsAdapterAndImplementation(clazz);
            }
        }
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testSucessfulAdaptations() {
        for (Class<?> clazz : this.getClass().getDeclaredClasses()) {
            if (!clazz.isInterface() && clazz.getSimpleName().startsWith("Successful")) {
                successful((Class<Methods>) clazz);
            }
        }
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testFailingAdaptations() {
        for (Class<?> clazz : this.getClass().getDeclaredClasses()) {
            if (!clazz.isInterface() && clazz.getSimpleName().startsWith("Failing")) {
                failing((Class<Methods>) clazz);
            }
        }
    }

    // @Optional overrides default optional=false from annotation
    @Model(adaptables = Resource.class)
    public static class SuccessfulSingleOptionalBySeparateAnnotationFieldModel implements Methods {

        @ValueMapValue
        private String otherText;

        @Override
        public String getOtherText() {
            return otherText;
        }

        @ValueMapValue
        @Optional
        private String emptyText;

        @Override
        public String getEmptyText() {
            return emptyText;
        }
    }

    // optional=true attribute still works with no @Optional annotation
    @Model(adaptables = Resource.class)
    public static class SuccessfulSingleOptionalViaAttributeFieldModel implements Methods {

        @ValueMapValue
        private String otherText;

        @Override
        public String getOtherText() {
            return otherText;
        }

        @ValueMapValue(optional = true)
        private String emptyText;

        @Override
        public String getEmptyText() {
            return emptyText;
        }
    }

    // strategy still work with no @Optional attribute
    @Model(adaptables = Resource.class)
    public static class SuccessfulSingleOptionalByStrategyFieldModel implements Methods {

        @ValueMapValue
        private String otherText;

        @Override
        public String getOtherText() {
            return otherText;
        }

        @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL)
        private String emptyText;

        @Override
        public String getEmptyText() {
            return emptyText;
        }
    }

    // @Required overrides class-level strategy
    @Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
    public static class FailingSingleRequiredByAnnotationFieldModel implements Methods {

        @ValueMapValue
        private String otherText;

        @Override
        public String getOtherText() {
            return otherText;
        }

        @ValueMapValue
        @Required
        private String emptyText;

        @Override
        public String getEmptyText() {
            return emptyText;
        }
    }

    // REQUIRED strategy overrides class-level strategy
    @Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
    public static class FailingSingleRequiredByStrategyFieldModel implements Methods {

        @ValueMapValue
        private String otherText;

        @Override
        public String getOtherText() {
            return otherText;
        }

        @ValueMapValue(injectionStrategy = InjectionStrategy.REQUIRED)
        private String emptyText;

        @Override
        public String getEmptyText() {
            return emptyText;
        }
    }

    // optional=true overrides @Required annotation
    @Model(adaptables = Resource.class)
    public static class SuccessfulSingleRequiredBySeparateAnnotationOverridingAttributeFieldModel implements Methods {

        @ValueMapValue
        private String otherText;

        @Override
        public String getOtherText() {
            return otherText;
        }

        @ValueMapValue(optional = true)
        @Required
        private String emptyText;

        @Override
        public String getEmptyText() {
            return emptyText;
        }
    }

    // @Required overrides OPTIONAL strategy
    @Model(adaptables = Resource.class)
    public static class FailingSingleRequiredBySeparateAnnotationOverridingStrategyFieldModel implements Methods {

        @ValueMapValue
        private String otherText;

        @Override
        public String getOtherText() {
            return otherText;
        }

        @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL)
        @Required
        private String emptyText;

        @Override
        public String getEmptyText() {
            return emptyText;
        }
    }

    private interface Methods {
        String getOtherText();
        String getEmptyText();
    }

    private <T extends Methods> void successful(Class<T> modelClass) {
        ValueMap map = new ValueMapDecorator(Collections.<String, Object>singletonMap("otherText", "hello"));
        when(resource.adaptTo(ValueMap.class)).thenReturn(map);

        Methods model = factory.createModel(resource, modelClass);
        assertNotNull("Adaptation to " + modelClass.getSimpleName() + " was not null.", model);
        assertNull("Adaptation to " + modelClass.getSimpleName() + " had a non-null emptyText value.", model.getEmptyText());
        assertEquals("Adaptation to " + modelClass.getSimpleName() + " had an unexpected value in the otherText value.", "hello", model.getOtherText());
    }

    private <T extends Methods> void failing(Class<T> modelClass) {
        ValueMap map = new ValueMapDecorator(Collections.<String, Object>singletonMap("otherText", "hello"));
        when(resource.adaptTo(ValueMap.class)).thenReturn(map);

        boolean thrown = false;

        try {
            factory.createModel(resource, modelClass);
        } catch (MissingElementsException e) {
            assertEquals("Adaptation to " + modelClass.getSimpleName() + " failed, but with the wrong number of exceptions.",1, e.getMissingElements().size());
            MissingElementException me = e.getMissingElements().iterator().next();
            assertTrue("Adaptation to " + modelClass.getSimpleName() + " didn't fail due to emptyText.", me.getElement().toString().endsWith("emptyText"));
            thrown = true;
        }
        assertTrue("Adaptation to " + modelClass.getSimpleName() + " was successful.", thrown);
    }
}
