/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Denise Smith  June 05, 2009 - Initial implementation
package org.eclipse.persistence.testing.jaxb.listofobjects;

import java.io.InputStream;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.TreeSet;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.xml.bind.JAXBElement;
import javax.xml.namespace.QName;

public class JAXBListOfObjectsNonRootTestCases extends JAXBListOfObjectsNoJSONTestCases {

    protected final static String CONTROL_RESPONSIBILITY1 = "Fix Bugs";
    protected final static String CONTROL_RESPONSIBILITY2 = "Write JAXB2.0 Prototype";
    protected final static String CONTROL_RESPONSIBILITY3 = "Write Design Spec";
    protected final static String CONTROL_FIRST_NAME = "Bob";
    protected final static String CONTROL_LAST_NAME = "Smith";
    protected final static int CONTROL_ID = 10;

    private final static String XML_RESOURCE = "org/eclipse/persistence/testing/jaxb/listofobjects/listofobjects.xml";
    private final static String XML_RESOURCE_NO_XSI_TYPE = "org/eclipse/persistence/testing/jaxb/listofobjects/listofobjectsNoXsiType.xml";

    public JAXBListOfObjectsNonRootTestCases(String name) throws Exception {
        super(name);
        init();
    }

    @Override
    public void setUp() throws Exception{
        super.setUp();
        getXMLComparer().setIgnoreOrder(true);
    }

    @Override
    public void tearDown(){
        super.tearDown();
        getXMLComparer().setIgnoreOrder(false);
    }

    public void init() throws Exception {
        setControlDocument(XML_RESOURCE);
        setWriteControlDocument(XML_RESOURCE_NO_XSI_TYPE);
        Class[] classes = new Class[2];
        classes[0] = ListofObjects.class;
        classes[1] = Employee.class;
        setClasses(classes);
    }

       @Override
       public  List<InputStream> getControlSchemaFiles(){

           InputStream instream = ClassLoader.getSystemResourceAsStream("org/eclipse/persistence/testing/jaxb/listofobjects/listofobjects.xsd");

            List<InputStream> controlSchema = new ArrayList<InputStream>();
            controlSchema.add(instream);
            return controlSchema;
        }

    @Override
    protected Object getControlObject() {
        ListofObjects listofObjects = new ListofObjects();

        Vector<Integer> integers = new Vector<Integer>();
        integers.add(Integer.valueOf("10"));
        integers.add(Integer.valueOf("20"));
        integers.add(Integer.valueOf("30"));
        integers.add(Integer.valueOf("40"));

        listofObjects.setIntegerList(integers);


        TreeSet<Integer> integerSet = new TreeSet<Integer>();
        integerSet.add(Integer.valueOf("20"));
        integerSet.add(Integer.valueOf("40"));
        integerSet.add(Integer.valueOf("60"));
        listofObjects.setIntegerSet(integerSet);

        Integer[] integerArray = new Integer[4];
        integerArray[0] = 10;
        integerArray[1] = 20;
        integerArray[2] = 30;
        integerArray[3] = 40;
        listofObjects.setIntegerArray(integerArray);

        int[] intArray = new int[2];
        intArray[0] = 1;
        intArray[1] = 2;
        listofObjects.intArray = intArray;

        Employee[] empArray = new Employee[2];
        empArray[0] = getEmployee1();
        empArray[1] = getEmployee2();
        listofObjects.setEmpArray(empArray);

        List<Employee> empList = new ArrayList<Employee>();
        empList.add(getEmployee1());
        empList.add(getEmployee2());
        listofObjects.setEmpList(empList);

        boolean[] booleans = new boolean[4];
        booleans[0] = true;
        booleans[1] = true;
        booleans[2] = false;
        booleans[3] = false;
        listofObjects.setBooleanArray(booleans);

        HashMap<String, Integer> stringIntegerMap = new HashMap<String, Integer>();
        stringIntegerMap.put("string1", 10);
        stringIntegerMap.put("string2", 20);
        stringIntegerMap.put("string3", 30);
        listofObjects.setStringIntegerHashMap(stringIntegerMap);

        ConcurrentHashMap<String, Integer> stringIntegerConcurrentMap = new ConcurrentHashMap<String, Integer>();
        stringIntegerConcurrentMap.put("string1", 10);
        stringIntegerConcurrentMap.put("string2", 20);
        stringIntegerConcurrentMap.put("string3", 30);
        listofObjects.setStringIntegerConcurrentMap(stringIntegerConcurrentMap);

        LinkedList<Integer> integersLinkedList = new LinkedList<Integer>();
        integersLinkedList.add(5);
        integersLinkedList.add(15);
        integersLinkedList.add(25);
        listofObjects.setIntegerLinkedList(integersLinkedList);

        Hashtable<String, Employee> stringEmployeeTable = new Hashtable<String, Employee>();
        stringEmployeeTable.put("string1", getEmployee1());
        listofObjects.setStringEmployeeHashtable(stringEmployeeTable);

        Stack<BigDecimal> theStack = new Stack<BigDecimal>();
        theStack.push(new BigDecimal("1"));
        theStack.push(new BigDecimal("5"));
        theStack.push(new BigDecimal("10"));
        listofObjects.setBigDecimalStack(theStack);

        MyList<String> test = new MyList<String>();
        test.add("aaa");
        test.add("bbb");
        test.add("ccc");
        listofObjects.setStringMyList(test);

        LinkedList stringQueue = new LinkedList<String>();
        stringQueue.add("ddd");
        stringQueue.add("eee");
        listofObjects.setStringQueue(stringQueue);

        QName qname = new QName("listOfObjectsNamespace", "root");
        JAXBElement jaxbElement = new JAXBElement(qname, Object.class, null);
        jaxbElement.setValue(listofObjects);
        return jaxbElement;
    }

    @Override
    protected Type getTypeToUnmarshalTo() {
        return ListofObjects.class;
    }

    private Employee getEmployee1() {
        ArrayList responsibilities = new ArrayList();
        responsibilities.add(CONTROL_RESPONSIBILITY1);
        responsibilities.add(CONTROL_RESPONSIBILITY2);
        responsibilities.add(CONTROL_RESPONSIBILITY3);

        Employee employee = new Employee();
        employee.firstName = CONTROL_FIRST_NAME;
        employee.lastName = CONTROL_LAST_NAME;

        Calendar cal = Calendar.getInstance();
        cal.clear();
        cal.set(2005, 04, 24, 16, 06, 53);

        employee.id = CONTROL_ID;

        employee.responsibilities = responsibilities;

        employee.setBlah("Some String");

        return employee;
    }

    private Employee getEmployee2() {
        Employee employee2 = new Employee();
        employee2.firstName = CONTROL_FIRST_NAME + "2";
        employee2.lastName = CONTROL_LAST_NAME + "2";
        employee2.setBlah("Some Other String");
        employee2.id = 100;

        ArrayList responsibilities2 = new ArrayList();
        responsibilities2.add(CONTROL_RESPONSIBILITY1);
        employee2.responsibilities = responsibilities2;
        return employee2;

    }

    @Override
    protected String getNoXsiTypeControlResourceName() {
        return XML_RESOURCE_NO_XSI_TYPE;
    }


    public void testTypeToSchemaTypeMap(){
        Map<Type, QName> typesMap = ((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getTypeToSchemaType();
        int mapSize = typesMap.size();
        assertEquals(2, mapSize);
    }

}
