/*
 * Copyright (c) 2011, 2020 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:
//     Matt MacIvor - 2.4 - initial implementation
package org.eclipse.persistence.testing.jaxb.dynamic.withstatic;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.internal.dynamic.DynamicEntityImpl;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
import org.eclipse.persistence.testing.jaxb.JAXBWithJSONTestCases;

public class StaticWithDynamicTestCases extends JAXBWithJSONTestCases {

//    private DynamicJAXBContext jaxbContext;
    private static final String RESOURCE_DIR = "org/eclipse/persistence/testing/jaxb/dynamic/withstatic/";

    // Schema files used to test each feature
    private static final String NO_ADDRESS = RESOURCE_DIR + "address-with-phone-oxm.xml";
    private static final String CONTROL_DOC = RESOURCE_DIR + "customer3.xml";
    private static final String JSON_CONTROL_DOC = RESOURCE_DIR + "customer3.json";
    private static final String PACKAGE = "org.eclipse.persistence.testing.jaxb.dynamic.withstatic";

    public StaticWithDynamicTestCases(String name) throws Exception {
        super(name);
        setupContext();
        setControlDocument(CONTROL_DOC);
        setControlJSON(JSON_CONTROL_DOC);
    }

    public String getName() {
        return "Dynamic JAXB: OXM: " + super.getName();
    }

    @Override
    protected Object getControlObject() {
        DynamicEntity customer = ((DynamicJAXBContext)jaxbContext).newDynamicEntity(PACKAGE + "." + "Customer");
        DynamicEntity phone1 = ((DynamicJAXBContext)jaxbContext).newDynamicEntity(PACKAGE + "." + "PhoneNumber");
        DynamicEntity phone2 = ((DynamicJAXBContext)jaxbContext).newDynamicEntity(PACKAGE + "." + "PhoneNumber");
        DynamicEntity phone3 = ((DynamicJAXBContext)jaxbContext).newDynamicEntity(PACKAGE + "." + "PhoneNumber");
        phone1.set("value", "555-WORK");
        phone1.set("type", "work");
        phone2.set("value", "555-HOME");
        phone2.set("type", "home");
        phone3.set("value", "555-CELL");
        phone3.set("type", "cell");

        ArrayList phones = new ArrayList();
        phones.add(phone1);
        phones.add(phone2);
        customer.set("phoneNumber", phones);

        AddressWithPhone address = new AddressWithPhone();
        address.city = "Any Town";
        address.street = "123 Some Street";
        address.phone = phone3;

        customer.set("address", address);
        customer.set("name", "Jane Doe");

        return customer;
    }



    void setupContext() throws Exception {
        classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(NO_ADDRESS);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + NO_ADDRESS + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContext(PACKAGE, null, properties);
        xmlContext = ((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext();
        setProject(xmlContext.getSession(0).getProject());
        jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        jaxbMarshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "value");
        jaxbUnmarshaller.setProperty(UnmarshallerProperties.JSON_VALUE_WRAPPER, "value");
    }

    public void xmlToObjectTest(Object testObject, Object controlObject) throws Exception {
        log("\n**xmlToObjectTest**");
        log("Expected:");
        log(controlObject.toString());
        log("Actual:");
        log(testObject.toString());

        compareDynamicEntities(testObject, controlObject);
    }

    public void jsonToObjectTest(Object testObject) throws Exception {
        log("\n**xmlToObjectTest**");
        log("Expected:");
        log(getReadControlObject().toString());
        log("Actual:");
        log(testObject.toString());
        compareDynamicEntities(testObject, getReadControlObject());
    }

    private void compareDynamicEntities(Object testObject, Object controlObject) {
        if(testObject instanceof DynamicEntity && controlObject instanceof DynamicEntity) {
            DynamicEntity test = (DynamicEntity)testObject;
            DynamicEntity control = (DynamicEntity)controlObject;
            for(String key: ((DynamicEntityImpl)test).getPropertiesMap().keySet()) {
                Object testValue = test.get(key);
                Object controlValue = control.get(key);
                if(testValue instanceof List && controlValue instanceof List) {
                    for(int i = 0; i < ((List)testValue).size(); i++) {
                        Object nextTestValue = ((List)testValue).get(i);
                        Object nextControlValue = ((List)controlValue).get(i);
                        if(nextTestValue instanceof DynamicEntity) {
                            compareDynamicEntities(nextTestValue, nextControlValue);
                        } else {
                            assertEquals(nextTestValue, nextControlValue);
                        }
                    }
                }
                else if(testValue instanceof DynamicEntity) {
                    compareDynamicEntities(testValue, controlValue);
                } else {
                    assertEquals(testValue, controlValue);
                }
            }
        } else {
            assertEquals(testObject, controlObject);
        }

    }
}
