/*
 * 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.camel.core.xml;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import static java.util.Arrays.asList;
import static java.util.Arrays.stream;

import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.Service;
import org.apache.camel.TypeConverter;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.impl.converter.DefaultTypeConverter;
import org.apache.camel.impl.engine.DefaultClassResolver;
import org.apache.camel.impl.engine.DefaultFactoryFinder;
import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
import org.apache.camel.model.ModelCamelContext;
import org.apache.camel.spi.ExecutorServiceManager;
import org.apache.camel.spi.Injector;
import org.apache.camel.spi.ManagementNameStrategy;
import org.apache.camel.spi.RuntimeEndpointRegistry;
import org.apache.camel.support.ObjectHelper;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.Invocation;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;

public class AbstractCamelContextFactoryBeanTest {

    // any properties (abstract methods in AbstractCamelContextFactoryBean that
    // return String and receive no arguments) that do not support property
    // placeholders
    Set<String> propertiesThatAreNotPlaceholdered = Collections.singleton("{{getErrorHandlerRef}}");

    TypeConverter typeConverter = new DefaultTypeConverter(new DefaultPackageScanClassResolver(),
        new Injector() {
            @Override
            public <T> T newInstance(Class<T> type) {
                return newInstance(type, false);
            }

            @Override
            public <T> T newInstance(Class<T> type, String factoryMethod) {
                return null;
            }

            @Override
            public <T> T newInstance(Class<T> type, boolean postProcessBean) {
                return ObjectHelper.newInstance(type);
            }

            @Override
            public boolean supportsAutoWiring() {
                return false;
            }
        },
        new DefaultFactoryFinder(new DefaultClassResolver(), "META-INF/services/org/apache/camel/"), false);

    // properties that should return value that can be converted to boolean
    Set<String> valuesThatReturnBoolean = new HashSet<>(asList("{{getStreamCache}}", "{{getTrace}}",
        "{{getMessageHistory}}", "{{getLogMask}}", "{{getLogExhaustedMessageBody}}", "{{getHandleFault}}",
        "{{getAutoStartup}}", "{{getUseMDCLogging}}", "{{getUseDataType}}", "{{getUseBreadcrumb}}", "{{getAllowUseOriginalMessage}}"));

    // properties that should return value that can be converted to long
    Set<String> valuesThatReturnLong = new HashSet<>(asList("{{getDelayer}}"));

    public AbstractCamelContextFactoryBeanTest() throws Exception {
        ((Service) typeConverter).start();
    }

    @Test
    public void shouldSupportPropertyPlaceholdersOnAllProperties() throws Exception {
        final Set<Invocation> invocations = new LinkedHashSet<>();

        final DefaultCamelContext context = mock(DefaultCamelContext.class,
            withSettings().invocationListeners(i -> invocations.add((Invocation) i.getInvocation())));

        when(context.adapt(ExtendedCamelContext.class)).thenReturn(context);

        // program the property resolution in context mock
        when(context.resolvePropertyPlaceholders(anyString())).thenAnswer(invocation -> {
            final String placeholder = invocation.getArgument(0);

            // we receive the argument and check if the method should return a
            // value that can be converted to boolean
            if (valuesThatReturnBoolean.contains(placeholder) || placeholder.endsWith("Enabled}}")) {
                return "true";
            }

            // or long
            if (valuesThatReturnLong.contains(placeholder)) {
                return "1";
            }

            // else is just plain string
            return "string";
        });
        when(context.getTypeConverter()).thenReturn(typeConverter);
        when(context.getRuntimeEndpointRegistry()).thenReturn(mock(RuntimeEndpointRegistry.class));
        when(context.getManagementNameStrategy()).thenReturn(mock(ManagementNameStrategy.class));
        when(context.getExecutorServiceManager()).thenReturn(mock(ExecutorServiceManager.class));

        @SuppressWarnings("unchecked")
        final AbstractCamelContextFactoryBean<ModelCamelContext> factory = mock(AbstractCamelContextFactoryBean.class);
        when(factory.getContext()).thenReturn(context);
        doCallRealMethod().when(factory).initCamelContext(context);

        final Set<String> expectedPropertiesToBeResolved = propertiesToBeResolved(factory);

        // method under test
        factory.initCamelContext(context);

        // we want to capture the arguments initCamelContext tried to resolve
        // and check if it tried to resolve all placeholders we expected
        final ArgumentCaptor<String> capturedPlaceholders = ArgumentCaptor.forClass(String.class);
        verify(context, atLeastOnce()).resolvePropertyPlaceholders(capturedPlaceholders.capture());

        // removes any properties that are not using property placeholders
        expectedPropertiesToBeResolved.removeAll(propertiesThatAreNotPlaceholdered);

        assertThat(capturedPlaceholders.getAllValues())
            .as("The expectation is that all abstract getter methods that return Strings should support property "
                + "placeholders, and that for those will delegate to CamelContext::resolvePropertyPlaceholders, "
                + "we captured all placeholders that tried to resolve and found differences")
            .containsAll(expectedPropertiesToBeResolved);
    }

    Set<String> propertiesToBeResolved(final AbstractCamelContextFactoryBean<ModelCamelContext> factory) {
        final Set<String> expectedPropertiesToBeResolved = new HashSet<>();

        // looks at all abstract methods in AbstractCamelContextFactoryBean that
        // do have no declared parameters and programs the mock to return
        // "{{methodName}}" on calling that method, this happens when
        // AbstractCamelContextFactoryBean::initContext invokes the programmed
        // mock, so the returned collection will be empty until initContext
        // invokes the mocked method
        stream(AbstractCamelContextFactoryBean.class.getDeclaredMethods())
            .filter(m -> Modifier.isAbstract(m.getModifiers()) && m.getParameterCount() == 0).forEach(m -> {
                try {
                    when(m.invoke(factory)).thenAnswer(invocation -> {
                        final Method method = invocation.getMethod();

                        final String name = method.getName();

                        if (String.class.equals(method.getReturnType())) {
                            final String placeholder = "{{" + name + "}}";
                            expectedPropertiesToBeResolved.add(placeholder);
                            return placeholder;
                        }

                        return null;
                    });
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ignored) {
                    // ignored
                }
            });

        return expectedPropertiesToBeResolved;
    }

    static boolean shouldProvidePropertyPlaceholderSupport(final Method method) {
        // all abstract getter methods that return String are possibly returning
        // strings that contain property placeholders

        final boolean isAbstract = Modifier.isAbstract(method.getModifiers());
        final boolean isGetter = method.getName().startsWith("get");
        final Class<?> returnType = method.getReturnType();

        final boolean isCompatibleReturnType = String.class.isAssignableFrom(returnType);

        return isAbstract && isGetter && isCompatibleReturnType;
    }

}
