/*
 * 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.commons.beanutils2;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * <p>Test Case for the {@code LazyDynaList}class.</p>
 *
 */
public class LazyDynaListTestCase extends TestCase {

    private static final String BASIC_PROP1 = "BasicDynaClass_Property1";
    private static final String BASIC_PROP2 = "BasicDynaClass_Property2";

    protected DynaProperty[] properties = new DynaProperty[] {
                                               new DynaProperty(BASIC_PROP1, String.class),
                                               new DynaProperty(BASIC_PROP2, HashMap.class)};

    protected DynaClass treeMapDynaClass = new LazyDynaMap(new TreeMap<String, Object>());
    protected DynaClass hashMapDynaClass = new LazyDynaMap(new HashMap<String, Object>());
    protected DynaClass pojoDynaClass = new WrapDynaBean(new TestBean()).getDynaClass();
    protected DynaClass basicDynaClass = new BasicDynaClass("test", BasicDynaBean.class, properties);



    /**
     * Construct a new instance of this test case.
     *
     * @param name Name of the test case
     */
    public LazyDynaListTestCase(final String name) {
        super(name);
    }



    /**
     * Run thus Test
     */
    public static void main(final String[] args) {
        junit.textui.TestRunner.run(suite());
    }

    /**
     * Return the tests included in this test suite.
     */
    public static Test suite() {
        return new TestSuite(LazyDynaListTestCase.class);
    }

    /**
     * Set up instance variables required by this test case.
     */
    @Override
    public void setUp() throws Exception {
    }

    /**
     * Tear down instance variables required by this test case.
     */
    @Override
    public void tearDown() {
    }



    /**
     * Test DynaBean Create
     */
    public void testDynaBeanDynaClass() {

        // Create LazyArrayList for DynaBeans
        final LazyDynaList list = new LazyDynaList(basicDynaClass);

        // test
        dynaBeanTest(list, BasicDynaBean.class, basicDynaClass, new BenchBean());
    }

    /**
     * Test DynaBean Create
     */
    public void testDynaBeanType() {

        // Create LazyArrayList for DynaBeans
        final LazyDynaList list = new LazyDynaList(LazyDynaBean.class);

        final LazyDynaBean bean = new LazyDynaBean();
        bean.set("prop1", "val");

        // test
        dynaBeanTest(list, LazyDynaBean.class, bean.getDynaClass(), new BenchBean());
    }

    /**
     * Test Map Create
     */
    public void testMapDynaClass() {

        // Create LazyArrayList for TreeMap's
        final LazyDynaList list = new LazyDynaList(treeMapDynaClass);

        // test
        mapTest(list, TreeMap.class, new BenchBean());

    }

    /**
     * Test Map Create
     */
    public void testMapType() {

        // Create LazyArrayList for HashMap's
        final LazyDynaList list = new LazyDynaList(HashMap.class);

        // test
        mapTest(list, HashMap.class, new BenchBean());

    }

    /**
     * Test Pojo Create
     */
    public void testPojoDynaClass() {

        // Create LazyArrayList for POJO's
        final LazyDynaList list = new LazyDynaList(pojoDynaClass);

        // test
        pojoTest(list, TestBean.class, new BenchBean());

    }

    /**
     * Test Pojo Create
     */
    public void testPojoType() {

        // Create LazyArrayList for POJO's
        final LazyDynaList list = new LazyDynaList(TestBean.class);

        // test
        pojoTest(list, TestBean.class, new BenchBean());

    }

    /**
     * Test Collection
     */
    public void testCollection(final LazyDynaList list, final Class<?> testClass, final DynaClass testDynaClass, final Object wrongBean) {

        // ----- Create Collection & Array of Maps -----
        final int size = 5;
        final List<Object> testList = new ArrayList<>(size);
        final TreeMap<?, ?>[] testArray = new TreeMap[size];
        for (int i = 0; i < size; i++) {
            final TreeMap<String, Object> map = new TreeMap<>();
            map.put("prop"+i, "val"+i);
            testArray[i] = map;
            testList.add(testArray[i]);
        }

        // ----- Create LazyArrayList from Collection -----
        LazyDynaList lazyList = new LazyDynaList(testList);
        assertEquals("1. check size", size, lazyList.size());

        DynaBean[] dynaArray = lazyList.toDynaBeanArray();
        TreeMap<?, ?>[]  mapArray  = (TreeMap[])lazyList.toArray();

        // Check values
        assertEquals("2. check size", size, dynaArray.length);
        assertEquals("3. check size", size, mapArray.length);
        for (int i = 0; i < size; i++) {
            assertEquals("4."+i+" DynaBean error ", "val"+i, dynaArray[i].get("prop"+i));
            assertEquals("5."+i+" Map error ", "val"+i, mapArray[i].get("prop"+i));
        }

        // ----- Create LazyArrayList from Array -----
        lazyList = new LazyDynaList(testArray);
        assertEquals("6. check size", size, lazyList.size());

        dynaArray = lazyList.toDynaBeanArray();
        mapArray  = (TreeMap[])lazyList.toArray();

        // Check values
        assertEquals("7. check size", size, dynaArray.length);
        assertEquals("8. check size", size, mapArray.length);
        for (int i = 0; i < size; i++) {
            assertEquals("9."+i+" DynaBean error ", "val"+i, dynaArray[i].get("prop"+i));
            assertEquals("10."+i+" Map error ", "val"+i, mapArray[i].get("prop"+i));
        }

    }

    /**
     * Test adding a map to List with no type set.
     */
    public void testNullType() {
        final LazyDynaList lazyList = new LazyDynaList();
        lazyList.add(new HashMap<String, Object>());
    }

    /**
     * Test DynaBean Create
     */
    private void dynaBeanTest(final LazyDynaList list, final Class<?> testClass, final DynaClass testDynaClass, final Object wrongBean) {

        // Test get(index) created correct DynaBean - Second
        Object dynaBean = list.get(1);
        assertNotNull("1. DynaBean Not Created", dynaBean);
        assertEquals("2. Wrong Type", testClass, dynaBean.getClass());

        // Test toArray() creates correct Array - Second
        Object array = list.toArray();
        assertNotNull("3. Array Not Created", array);
        assertEquals("4. Not DynaBean[]", testClass, array.getClass().getComponentType());
        DynaBean[] dynaArray = (DynaBean[])array;
        assertEquals("5. Array Size Wrong", 2, dynaArray.length);

        // Test get(index) created correct DynaBean - Fourth
        dynaBean = list.get(3);
        assertNotNull("6. DynaBean Not Created", dynaBean);
        assertEquals("7. Wrong type", testClass, dynaBean.getClass());

        // Test toArray() creates correct Array - Fourth
        array = list.toArray();
        assertNotNull("8. Array Not Created", array);
        assertEquals("9. Not DynaBean[]", testClass, array.getClass().getComponentType());
        dynaArray = (DynaBean[])array;
        assertEquals("10. Array Size Wrong", 4, dynaArray.length);

        // Test fail if different type added
        try {
            list.add(2, wrongBean);
            fail("Expected IllegalArgumentException");
        } catch(final IllegalArgumentException ignore) {
            // expected result
        }

        // find a String property to set
        final String testProperty = findStringProperty(testDynaClass);
        assertNotNull("Test Property Not Found", testProperty);
        dynaArray = list.toDynaBeanArray();
        for (int i = 0; i < dynaArray.length; i++) {
            dynaArray[i].set(testProperty, "orig_pos"+i);
        }

        // Create Collection
        final List<Object> collection = new ArrayList<>();
        try {
            collection.add(testDynaClass.newInstance());
            collection.add(testDynaClass.newInstance());
            collection.add(testDynaClass.newInstance());
        } catch(final Exception ex) {
            fail("1. FAILED: " + ex);
        }
        final int expectedSize = dynaArray.length + collection.size();
        final String origValue = (String)((DynaBean)collection.get(0)).get(testProperty);
        ((DynaBean)collection.get(0)).set(testProperty, origValue+"_updated_"+0);
        ((DynaBean)collection.get(1)).set(testProperty, origValue+"_updated_"+1);
        ((DynaBean)collection.get(2)).set(testProperty, origValue+"_updated_"+2);

        // Test Insert - addAll(index, Collection)
        list.addAll(1, collection);
        dynaArray = list.toDynaBeanArray();

        // Check array after insert
        dynaArray = list.toDynaBeanArray();
        assertEquals("11. Array Size Wrong", expectedSize, dynaArray.length);

        // Check Beans have inserted correctly - by checking the property values
        assertEquals("12. Wrong Value", "orig_pos0",             dynaArray[0].get(testProperty));
        assertEquals("13. Wrong Value", origValue+"_updated_"+0, dynaArray[1].get(testProperty));
        assertEquals("14. Wrong Value", origValue+"_updated_"+1, dynaArray[2].get(testProperty));
        assertEquals("15. Wrong Value", origValue+"_updated_"+2, dynaArray[3].get(testProperty));
        assertEquals("16. Wrong Value", "orig_pos1",             dynaArray[4].get(testProperty));

        // Test Insert - add(index, Object)
        try {
            final DynaBean extraElement = testDynaClass.newInstance();
            extraElement.set(testProperty, "extraOne");
            list.add(2, extraElement);
            dynaArray = list.toDynaBeanArray();
            assertEquals("17. Wrong Value", origValue+"_updated_"+0, dynaArray[1].get(testProperty));
            assertEquals("18. Wrong Value", "extraOne",              dynaArray[2].get(testProperty));
            assertEquals("19. Wrong Value", origValue+"_updated_"+1, dynaArray[3].get(testProperty));
        } catch(final Exception ex) {
            fail("2. FAILED: " + ex);
        }

    }

    /**
     * Test Map Create
     */
    private String findStringProperty(final DynaClass dynaClass) {
        final DynaProperty[] properties = dynaClass.getDynaProperties();
        for (final DynaProperty propertie : properties) {
            if (propertie.getType() == String.class) {
                return propertie.getName();
            }
        }
        return null;
    }

    /**
     * Test Map Create
     */
    private void mapTest(final LazyDynaList list, final Class<?> testClass, final Object wrongBean) {

        // Test get(index) created correct DynaBean - First
        Object dynaBean = list.get(0);
        assertNotNull("1. DynaBean Not Created", dynaBean);
        assertEquals("2. Not LazyDynaMap", LazyDynaMap.class, dynaBean.getClass());

        // Test get(index) created correct Map - First
        Object map = ((LazyDynaMap)dynaBean).getMap();
        assertNotNull("3. Map Not Created", map);
        assertEquals("4. Wrong Map", testClass, map.getClass());

        // Test toArray() creates correct Array - First
        Object array = list.toArray();
        assertNotNull("5. Array Not Created", array);
        assertEquals("6. Not Map[]", testClass, array.getClass().getComponentType());
        Map<?, ?>[] mapArray = (Map[])array;
        assertEquals("7. Array Size Wrong", 1, mapArray.length);

        // Test get(index) created correct DynaBean - Third
        dynaBean = list.get(2);
        assertNotNull("8. DynaBean Not Created", dynaBean);
        assertEquals("9. Not LazyDynaMap", LazyDynaMap.class, dynaBean.getClass());

        // Test get(index) created correct Map - Third
        map = ((LazyDynaMap)dynaBean).getMap();
        assertNotNull("10. Map Not Created", map);
        assertEquals("11. Wrong Map", testClass, map.getClass());

        // Test toArray() creates correct Array - Third
        array = list.toArray();
        assertNotNull("12. Array Not Created", array);
        assertEquals("13. Not Map[]", testClass, array.getClass().getComponentType());
        mapArray = (Map[])array;
        assertEquals("14. Array Size Wrong", 3, mapArray.length);

        // Test fail if different type added
        try {
            list.add(2, wrongBean);
            fail("Expected IllegalArgumentException");
        } catch(final IllegalArgumentException ignore) {
            // expected result
        }

    }

    /**
     * Test Pojo Create
     */
    private void pojoTest(final LazyDynaList list, final Class<?> testClass, final Object wrongBean) {

        // Test get(index) created correct DynaBean - First
        Object dynaBean = list.get(0);
        assertNotNull("1. DynaBean Not Created", dynaBean);
        assertEquals("2. Not WrapDynaBean", WrapDynaBean.class, dynaBean.getClass());

        // Test get(index) created correct POJO - First
        Object pojoBean = ((WrapDynaBean)dynaBean).getInstance();
        assertNotNull("3. POJO Not Created", pojoBean);
        assertEquals("4. Not WrapDynaBean", testClass, pojoBean.getClass());

        // Test toArray() creates correct Array - First
        Object array = list.toArray();
        assertNotNull("5. Array Not Created", array);
        assertEquals("6. Wrong array", testClass, array.getClass().getComponentType());
        Object[] pojoArray = (Object[])array;
        assertEquals("7. Array Size Wrong", 1, pojoArray.length);

        // Test get(index) created correct DynaBean - Second
        dynaBean = list.get(1);
        assertNotNull("8. DynaBean Not Created", dynaBean);
        assertEquals("9. Not WrapDynaBean", WrapDynaBean.class, dynaBean.getClass());

        // Test get(index) created correct POJO - Second
        pojoBean = ((WrapDynaBean)dynaBean).getInstance();
        assertNotNull("10. POJO Not Created", pojoBean);
        assertEquals("11. Not WrapDynaBean", testClass, pojoBean.getClass());

        // Test toArray() creates correct Array - Second
        array = list.toArray();
        assertNotNull("12. Array Not Created", array);
        assertEquals("13. Wrong array", testClass, array.getClass().getComponentType());
        pojoArray = (Object[])array;
        assertEquals("14. Array Size Wrong", 2, pojoArray.length);

        // Test fail if different type added
        try {
            list.add(2, wrongBean);
            fail("Expected IllegalArgumentException");
        } catch(final IllegalArgumentException ignore) {
            // expected result
        }

    }

    /**
     * Test DynaBean serialization.
     */
    public void testSerializationDynaBean() {

        // Create LazyArrayList for DynaBeans
        LazyDynaList target = new LazyDynaList(basicDynaClass);
        BasicDynaBean bean = (BasicDynaBean)target.get(0);

        // Set a Property
        assertNull("pre-set check", bean.get(BASIC_PROP1));
        bean.set(BASIC_PROP1, "value1");
        assertEquals("post-set check", "value1", bean.get(BASIC_PROP1));

        // Serialize/Deserialize
        final LazyDynaList result = (LazyDynaList)serializeDeserialize(target, "DynaBean");
        target = null;
        bean = null;

        // Confirm property value
        bean = (BasicDynaBean)result.get(0);
        assertEquals("post-serialize check", "value1", bean.get(BASIC_PROP1));

    }

    /**
     * Test DynaBean serialization.
     */
    public void testSerializationLazyDynaBean() {

        // Create LazyArrayList for DynaBeans
        LazyDynaList target = new LazyDynaList();
        LazyDynaBean bean = (LazyDynaBean)target.get(0);

        // Set a Property
        assertNull("pre-set check", bean.get(BASIC_PROP1));
        bean.set(BASIC_PROP1, "value1");
        assertEquals("post-set check", "value1", bean.get(BASIC_PROP1));

        // Serialize/Deserialize
        final LazyDynaList result = (LazyDynaList)serializeDeserialize(target, "DynaBean");
        target = null;
        bean = null;

        // Confirm property value
        bean = (LazyDynaBean)result.get(0);
        assertEquals("post-serialize check", "value1", bean.get(BASIC_PROP1));

    }

    /**
     * Test Map serialization.
     */
    public void testSerializationMap() {

        // Create LazyArrayList for DynaBeans
        LazyDynaList target = new LazyDynaList(treeMapDynaClass);
        LazyDynaMap bean = (LazyDynaMap)target.get(0);

        // Set a Property
        assertNull("pre-set check", bean.get(BASIC_PROP1));
        bean.set(BASIC_PROP1, "value1");
        assertEquals("post-set check", "value1", bean.get(BASIC_PROP1));

        // Serialize/Deserialize
        final LazyDynaList result = (LazyDynaList)serializeDeserialize(target, "Map");
        target = null;
        bean = null;

        // Confirm property value
        bean = (LazyDynaMap)result.get(0);
        assertEquals("post-serialize check", "value1", bean.get(BASIC_PROP1));

    }

    /**
     * Test POJO (WrapDynaBean) serialization.
     */
    public void testSerializationPojo() {

        // Create LazyArrayList for DynaBeans
        LazyDynaList target = new LazyDynaList(pojoDynaClass);
        WrapDynaBean bean = (WrapDynaBean)target.get(0);

        // Set a Property
        assertEquals("pre-set check", "This is a string", bean.get("stringProperty"));
        bean.set("stringProperty", "value1");
        assertEquals("post-set check", "value1", bean.get("stringProperty"));

        // Serialize/Deserialize
        final LazyDynaList result = (LazyDynaList)serializeDeserialize(target, "POJO");
        target = null;
        bean = null;

        // Test BEANUTILS-300
        result.add(null);

        // Confirm property value
        bean = (WrapDynaBean)result.get(0);
        assertEquals("post-serialize check", "value1", bean.get("stringProperty"));

    }

    /**
     * Do serialization and deserialization.
     */
    private Object serializeDeserialize(final Object target, final String text) {

        // Serialize the test object
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            final ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(target);
            oos.flush();
            oos.close();
        } catch (final Exception e) {
            fail(text + ": Exception during serialization: " + e);
        }

        // Deserialize the test object
        Object result = null;
        try {
            final ByteArrayInputStream bais =
                new ByteArrayInputStream(baos.toByteArray());
            final ObjectInputStream ois = new ObjectInputStream(bais);
            result = ois.readObject();
            bais.close();
        } catch (final Exception e) {
            fail(text + ": Exception during deserialization: " + e);
        }
        return result;

    }

    /**
     * Tests toArray() if the list contains DynaBean objects.
     */
    public void testToArrayDynaBeans() {
        final LazyDynaList list = new LazyDynaList(LazyDynaBean.class);
        final LazyDynaBean elem = new LazyDynaBean();
        list.add(elem);
        final LazyDynaBean[] beans = new LazyDynaBean[1];
        assertSame("Wrong array", beans, list.toArray(beans));
        assertSame("Wrong element", elem, beans[0]);
    }

    /**
     * Tests toArray() if the list contains maps.
     */
    public void testToArrayMapType() {
        final LazyDynaList list = new LazyDynaList(HashMap.class);
        final HashMap<String, Object> elem = new HashMap<>();
        list.add(elem);
        final Map<?, ?>[] array = new Map[1];
        assertSame("Wrong array", array, list.toArray(array));
        assertEquals("Wrong element", elem, array[0]);
    }

    /**
     * Tests toArray() for other bean elements.
     */
    public void testToArrayOtherType() {
        final LazyDynaList list = new LazyDynaList(TestBean.class);
        final TestBean elem = new TestBean();
        list.add(elem);
        final TestBean[] array = new TestBean[1];
        assertSame("Wrong array", array, list.toArray(array));
        assertEquals("Wrong element", elem, array[0]);
    }

    /**
     * Tests toArray() if the array's size does not fit the collection size.
     */
    public void testToArrayUnsufficientSize() {
        final LazyDynaList list = new LazyDynaList(LazyDynaBean.class);
        final LazyDynaBean elem = new LazyDynaBean();
        list.add(elem);
        final LazyDynaBean[] array = list.toArray(new LazyDynaBean[0]);
        assertEquals("Wrong array size", 1, array.length);
        assertEquals("Wrong element", elem, array[0]);
    }
}
