/*
 *
 * 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.qpid.server.model.testmodels.hierarchy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.common.collect.Lists;

import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.*;
import org.apache.qpid.server.model.testmodels.hierarchy.TestCar.Colour;
import org.apache.qpid.server.plugin.ConfiguredObjectAttributeInjector;
import org.apache.qpid.test.utils.QpidTestCase;

public class InjectedAttributeTest extends QpidTestCase
{

    private static class TestInjector implements ConfiguredObjectAttributeInjector
    {

        private Collection<ConfiguredObjectInjectedAttribute<?, ?>> _injectedAttributes;
        private Collection<ConfiguredObjectInjectedStatistic<?, ?>> _injectedStatistics;
        private Collection<ConfiguredObjectInjectedOperation<?>> _injectedOperations;

        private TestInjector(ConfiguredObjectInjectedAttribute<?, ?>... attributes)
        {
            this(Arrays.asList(attributes),
                 Collections.<ConfiguredObjectInjectedStatistic<?, ?>>emptyList(),
                 Collections.<ConfiguredObjectInjectedOperation<?>>emptyList());
        }

        private TestInjector(ConfiguredObjectInjectedStatistic<?, ?>... statistics)
        {
            this(Collections.<ConfiguredObjectInjectedAttribute<?, ?>>emptyList(),
                 Arrays.asList(statistics),
                 Collections.<ConfiguredObjectInjectedOperation<?>>emptyList());
        }

        private TestInjector(ConfiguredObjectInjectedOperation<?>... operations)
        {
            this(Collections.<ConfiguredObjectInjectedAttribute<?, ?>>emptyList(),
                 Collections.<ConfiguredObjectInjectedStatistic<?, ?>>emptyList(),
                 Arrays.asList(operations));
        }

        private TestInjector(final Collection<ConfiguredObjectInjectedAttribute<?, ?>> injectedAttributes,
                             final Collection<ConfiguredObjectInjectedStatistic<?, ?>> injectedStatistics,
                             final Collection<ConfiguredObjectInjectedOperation<?>> injectedOperations)
        {
            _injectedAttributes = injectedAttributes;
            _injectedStatistics = injectedStatistics;
            _injectedOperations = injectedOperations;
        }

        @Override
        public Collection<ConfiguredObjectInjectedAttribute<?, ?>> getInjectedAttributes()
        {
            return _injectedAttributes;
        }

        @Override
        public Collection<ConfiguredObjectInjectedStatistic<?, ?>> getInjectedStatistics()
        {
            return _injectedStatistics;
        }

        @Override
        public Collection<ConfiguredObjectInjectedOperation<?>> getInjectedOperations()
        {
            return _injectedOperations;
        }

        @Override
        public String getType()
        {
            return "TEST";
        }
    }

    public void testInjectedSettableAttributeWithDefault()
    {
        InjectedAttributeOrStatistic.TypeValidator validator =
                new InjectedAttributeOrStatistic.TypeValidator()
                {
                    @Override
                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
                    {
                        return TestCar.class.isAssignableFrom(type);
                    }
                };

        final ConfiguredSettableInjectedAttribute<?, ?> attrInjector =
                new ConfiguredSettableInjectedAttribute<TestCar<?>, Integer>("meaningOfLife",
                                                                             Integer.class,
                                                                             Integer.class,
                                                                             "42",
                                                                             false,
                                                                             true,
                                                                             false,
                                                                             "",
                                                                             false,
                                                                             "",
                                                                             "",
                                                                             null,
                                                                             "", validator, Initialization.none);

        TestModel model = new TestModel(null, new TestInjector(attrInjector));

        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);

        assertEquals("incorrect attribute value", Integer.valueOf(42), testCar.getAttribute("meaningOfLife"));

        testCar.setAttributes(Collections.<String,Object>singletonMap("meaningOfLife", 54));

        assertEquals("incorrect attribute value", Integer.valueOf(54), testCar.getAttribute("meaningOfLife"));

        Map<String, String> context = new HashMap<>(testCar.getContext());
        context.put("varieties","57");
        testCar.setAttributes(Collections.<String,Object>singletonMap("context", context));
        testCar.setAttributes(Collections.<String,Object>singletonMap("meaningOfLife", "${varieties}"));

        assertEquals("incorrect attribute value", Integer.valueOf(57), testCar.getAttribute("meaningOfLife"));

    }


    public void testInjectedSettableAttributeValidValues()
    {

        InjectedAttributeOrStatistic.TypeValidator validator =
                new InjectedAttributeOrStatistic.TypeValidator()
                {
                    @Override
                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
                    {
                        return TestCar.class.isAssignableFrom(type);
                    }
                };

        final ConfiguredSettableInjectedAttribute<?, ?> attrInjector =
                new ConfiguredSettableInjectedAttribute<TestCar<?>, Integer>("meaningOfLife",
                                                                             Integer.class,
                                                                             Integer.class,
                                                                             "42",
                                                                             false,
                                                                             true,
                                                                             false,
                                                                             "",
                                                                             false,
                                                                             "",
                                                                             "",
                                                                             new String[] { "42", "49" },
                                                                             "", validator, Initialization.none);

        TestModel model = new TestModel(null, new TestInjector(attrInjector));

        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);

        assertEquals("incorrect attribute value", Integer.valueOf(42), testCar.getAttribute("meaningOfLife"));

        testCar.setAttributes(Collections.<String,Object>singletonMap("meaningOfLife", 49));


        assertEquals("incorrect attribute value", Integer.valueOf(49), testCar.getAttribute("meaningOfLife"));

        try
        {
            testCar.setAttributes(Collections.<String, Object>singletonMap("meaningOfLife", 54));
            fail("Should not be able to set attribute value to 54 as it is not a valid value");
        }
        catch (IllegalConfigurationException e)
        {
            // pass
        }
    }

    public void testInjectedSettableAttributeEnumValidValues_Unrestricted()
    {
        final ConfiguredSettableInjectedAttribute<?, ?> attribute =
                new ConfiguredSettableInjectedAttribute<TestCar<?>, Colour>("trimColour",
                                                                            Colour.class,
                                                                            Colour.class,
                                                                            Colour.BLACK.name(),
                                                                            false,
                                                                            true,
                                                                            false,
                                                                            "",
                                                                            false,
                                                                            "",
                                                                            "",
                                                                            null,
                                                                            "",
                                                                            null, Initialization.none);

        assertEquals("The attribute's valid values should match the set of the enum",
                     Lists.newArrayList("BLACK", "RED", "BLUE", "GREY"),
                     attribute.validValues());
    }

    public void testInjectedSettableAttributeEnumValidValues_RestrictedSet()
    {
        final ConfiguredSettableInjectedAttribute<?, ?> attribute =
                new ConfiguredSettableInjectedAttribute<TestCar<?>, Colour>("trimColour",
                                                                            Colour.class,
                                                                            Colour.class,
                                                                            Colour.BLACK.name(),
                                                                            false,
                                                                            true,
                                                                            false,
                                                                            "",
                                                                            false,
                                                                            "",
                                                                            "",
                                                                            new String[] {Colour.GREY.name(), Colour.BLACK.name()},
                                                                            "",
                                                                            null, Initialization.none);

        assertEquals("The attribute's valid values should match the restricted set defined on the attribute itself",
                     Lists.newArrayList("GREY", "BLACK"),
                     attribute.validValues());
    }

    public void testInjectedDerivedAttribute() throws Exception
    {
        Method method = InjectedAttributeTest.class.getDeclaredMethod("getMeaningOfLife", TestCar.class);
        InjectedAttributeOrStatistic.TypeValidator validator =
                new InjectedAttributeOrStatistic.TypeValidator()
                {
                    @Override
                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
                    {
                        return TestCar.class.isAssignableFrom(type);
                    }
                };

        final ConfiguredDerivedInjectedAttribute<?, ?> attrInjector =
                new ConfiguredDerivedInjectedAttribute<TestCar<?>, Integer>("meaningOfLife",
                                                                            method,
                                                                            null, false,
                                                                            false,
                                                                            "",
                                                                            false,
                                                                            "",
                                                                            "",
                                                                            validator);

        TestModel model = new TestModel(null, new TestInjector(attrInjector));

        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);


        assertEquals("incorrect attribute value", Integer.valueOf(42), testCar.getAttribute("meaningOfLife"));

    }


    public void testInjectedStatistic() throws Exception
    {

        Method method = InjectedAttributeTest.class.getDeclaredMethod("getMeaningOfLife", TestCar.class);
        InjectedAttributeOrStatistic.TypeValidator validator =
                new InjectedAttributeOrStatistic.TypeValidator()
                {
                    @Override
                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
                    {
                        return TestCar.class.isAssignableFrom(type);
                    }
                };

        final ConfiguredObjectInjectedStatistic<?, ?> statInjector =
                new ConfiguredObjectInjectedStatistic<TestCar<?>, Integer>("meaningOfLife",
                                                                           method,
                                                                           null, "",
                                                                           validator,
                                                                           StatisticUnit.COUNT,
                                                                           StatisticType.POINT_IN_TIME,
                                                                           "What is 6 x 9?");

        TestModel model = new TestModel(null, new TestInjector(statInjector));

        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);

        final Map<String, Object> statistics = testCar.getStatistics();
        assertEquals("incorrect number of statistics", 1, statistics.size());
        assertEquals("incorrect statistic value", 42, statistics.get("meaningOfLife"));
    }


    public void testInjectedStatisticWithParameters() throws Exception
    {

        Method method = InjectedAttributeTest.class.getDeclaredMethod("getWhatISent", TestCar.class, Integer.TYPE);
        InjectedAttributeOrStatistic.TypeValidator validator =
                new InjectedAttributeOrStatistic.TypeValidator()
                {
                    @Override
                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
                    {
                        return TestCar.class.isAssignableFrom(type);
                    }
                };

        final ConfiguredObjectInjectedStatistic<?, ?> statInjector1 =
                new ConfiguredObjectInjectedStatistic<TestCar<?>, Integer>("whatISent1",
                                                                           method,
                                                                           new Object[] { 1 }, "",
                                                                           validator,
                                                                           StatisticUnit.COUNT,
                                                                           StatisticType.POINT_IN_TIME,
                                                                           "One");
        final ConfiguredObjectInjectedStatistic<?, ?> statInjector2 =
                new ConfiguredObjectInjectedStatistic<TestCar<?>, Integer>("whatISent2",
                                                                           method,
                                                                           new Object[] { 2 }, "",
                                                                           validator,
                                                                           StatisticUnit.COUNT,
                                                                           StatisticType.POINT_IN_TIME,
                                                                           "Two");
        TestModel model = new TestModel(null, new TestInjector(statInjector1, statInjector2));

        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);

        final Map<String, Object> statistics = testCar.getStatistics();
        assertEquals("incorrect number of statistics", 2, statistics.size());
        assertEquals("incorrect statistic value", 1, statistics.get("whatISent1"));
        assertEquals("incorrect statistic value", 2, statistics.get("whatISent2"));
    }


    public void testInjectedOperation() throws Exception
    {

        Method method = InjectedAttributeTest.class.getDeclaredMethod("fly", TestCar.class, Integer.TYPE);
        InjectedAttributeOrStatistic.TypeValidator validator =
                new InjectedAttributeOrStatistic.TypeValidator()
                {
                    @Override
                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
                    {
                        return TestCar.class.isAssignableFrom(type);
                    }
                };

        final OperationParameter[] params = new OperationParameter[1];
        params[0] = new OperationParameterFromInjection("height", Integer.TYPE, Integer.TYPE, "", "", new String[0]);
        final ConfiguredObjectInjectedOperation<?> operationInjector =
                new ConfiguredObjectInjectedOperation<TestCar<?>>("fly", "", true,
                                                                  false,
                                                                  "", params, method, null, validator);

        TestModel model = new TestModel(null, new TestInjector(operationInjector));

        TestCar testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);

        final Map<String, ConfiguredObjectOperation<?>> allOperations =
                model.getTypeRegistry().getOperations(testCar.getClass());

        assertTrue("Operation fly(int height) is missing", allOperations.containsKey("fly"));

        final ConfiguredObjectOperation foundOperation = allOperations.get("fly");

        Object result = foundOperation.perform(testCar, Collections.<String, Object>singletonMap("height", 0));

        assertEquals("Car should be able to fly at 0m", Boolean.TRUE, result);

        result = foundOperation.perform(testCar, Collections.<String, Object>singletonMap("height", 5000));

        assertEquals("Car should not be able to fly at 5000m", Boolean.FALSE, result);
    }

    public void testInjectedOperationWithStaticParams() throws Exception
    {

        Method method = InjectedAttributeTest.class.getDeclaredMethod("saySomething", TestCar.class, String.class, Integer.TYPE);
        InjectedAttributeOrStatistic.TypeValidator validator =
                new InjectedAttributeOrStatistic.TypeValidator()
                {
                    @Override
                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
                    {
                        return TestCar.class.isAssignableFrom(type);
                    }
                };

        final OperationParameter[] params = new OperationParameter[1];
        params[0] = new OperationParameterFromInjection("count", Integer.TYPE, Integer.TYPE, "", "", new String[0]);

        final ConfiguredObjectInjectedOperation<?> hello =
                new ConfiguredObjectInjectedOperation<TestCar<?>>("sayHello", "", true,
                                                                  false,
                                                                  "", params, method, new String[] { "Hello"}, validator
                );
        final ConfiguredObjectInjectedOperation<?> goodbye =
                new ConfiguredObjectInjectedOperation<TestCar<?>>("sayGoodbye", "", true,
                                                                  false,
                                                                  "",
                                                                  params, method, new String[] { "Goodbye"}, validator
                );

        TestModel model = new TestModel(null, new TestInjector(hello, goodbye));

        TestCar testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);

        final Map<String, ConfiguredObjectOperation<?>> allOperations =
                model.getTypeRegistry().getOperations(testCar.getClass());

        assertTrue("Operation sayHello(int count) is missing", allOperations.containsKey("sayHello"));
        assertTrue("Operation sayGoodbye(int count) is missing", allOperations.containsKey("sayGoodbye"));

        final ConfiguredObjectOperation helloOperation = allOperations.get("sayHello");
        final ConfiguredObjectOperation goodbyeOperation = allOperations.get("sayGoodbye");

        Object result = helloOperation.perform(testCar, Collections.<String, Object>singletonMap("count", 3));

        assertEquals("Car should say 'Hello' 3 times", Arrays.asList("Hello", "Hello", "Hello"), result);

        result = goodbyeOperation.perform(testCar, Collections.<String, Object>singletonMap("count", 1));

        assertEquals("Car say 'Goodbye' once", Collections.singletonList("Goodbye"), result);
    }


    public static int getMeaningOfLife(TestCar<?> car)
    {
        return 42;
    }


    public static int getWhatISent(TestCar<?> car, int whatIsent)
    {
        return whatIsent;
    }

    public static boolean fly(TestCar<?> car, int height)
    {
        return height == 0;
    }

    public static List<String> saySomething(TestCar<?> car, String whatToSay, int count)
    {
        List<String> list = new ArrayList<>();
        for(int i = 0; i < count; i++)
        {
            list.add(whatToSay);
        }
        return list;
    }
}
