/*
 * 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 -  November, 2009
package org.eclipse.persistence.testing.jaxb.typemappinginfo;

import java.awt.Image;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import jakarta.activation.DataHandler;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.SchemaOutputResolver;
import jakarta.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBMarshaller;
import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.TypeMappingInfo;

import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.testing.jaxb.JAXBXMLComparer;
import org.eclipse.persistence.testing.oxm.OXTestCase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import static org.eclipse.persistence.testing.jaxb.JAXBTestCases.ECLIPSELINK_OXM_XSD;

public abstract class TypeMappingInfoTestCases extends OXTestCase {
    protected JAXBContext jaxbContext;
    protected Marshaller jaxbMarshaller;
    protected Unmarshaller jaxbUnmarshaller;
    public String resourceName;
    protected Document controlDocument;
    protected Document writeControlDocument;

    protected DocumentBuilder parser;
    protected Source bindingsFileXSDSource;
    protected String controlDocumentLocation;
    protected String writeControlDocumentLocation;

    protected TypeMappingInfo[] typeMappingInfos;

    public TypeMappingInfoTestCases(String name) throws Exception {
        super(name);
    }

    @Override
    public void setUp() throws Exception {
        setupParser();
        setupControlDocs();

        InputStream bindingsFileXSDInputStream = getClass().getClassLoader().getResourceAsStream(ECLIPSELINK_OXM_XSD);
        if(bindingsFileXSDInputStream == null){
            bindingsFileXSDInputStream = getClass().getClassLoader().getResourceAsStream("org/eclipse/persistence/jaxb/" + ECLIPSELINK_OXM_XSD);
        }
        if(bindingsFileXSDInputStream == null){
            fail("ERROR LOADING " + ECLIPSELINK_OXM_XSD);
        }
        bindingsFileXSDSource = new StreamSource(bindingsFileXSDInputStream);
    }

    @Override
    public void tearDown() throws Exception{
        super.tearDown();
        jaxbContext = null;
        jaxbMarshaller = null;
        jaxbUnmarshaller = null;
    }


    public void setTypeMappingInfos(TypeMappingInfo[] newTypes) throws Exception {
        typeMappingInfos = newTypes;

        Map props = getProperties();
        if(props != null){
            Map overrides = (Map) props.get(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY);
            if(overrides != null){
                Iterator valuesIter = overrides.values().iterator();
                while(valuesIter.hasNext()){
                    Source theSource = (Source) valuesIter.next();
                    validateBindingsFileAgainstSchema(theSource);
                }
            }
        }

        jaxbContext  = org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(newTypes, props, Thread.currentThread().getContextClassLoader());
        jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbUnmarshaller = jaxbContext.createUnmarshaller();
     }
    public TypeMappingInfo getTypeMappingInfo(){
        return typeMappingInfos[0];
    }

    protected Map getProperties() {
        return null;
    }

    public void testXMLToObjectFromXMLEventReaderWithTypeMappingInfo() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            javax.xml.stream.XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(instream);
            Object obj = ((org.eclipse.persistence.jaxb.JAXBUnmarshaller)jaxbUnmarshaller).unmarshal(reader, getTypeMappingInfo());

            Object controlObj = getReadControlObject();
            xmlToObjectTest(obj, controlObj);
        }
    }

    public void testXMLToObjectFromXMLStreamReaderWithTypeMappingInfo() throws Exception {
        if(null != XML_INPUT_FACTORY) {
            InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
            XMLStreamReader xmlStreamReader = XML_INPUT_FACTORY.createXMLStreamReader(instream);
            Object testObject = ((JAXBUnmarshaller)jaxbUnmarshaller).unmarshal(xmlStreamReader, getTypeMappingInfo());
            instream.close();

            Object controlObj = getReadControlObject();
            xmlToObjectTest(testObject, controlObj);
        }
    }

    public void testXMLToObjectFromSourceWithTypeMappingInfoXML() throws Exception {
        InputStream instream = ClassLoader.getSystemResourceAsStream(resourceName);
        StreamSource ss = new StreamSource(instream);
        Object testObject = ((JAXBUnmarshaller)jaxbUnmarshaller).unmarshal(ss, getTypeMappingInfo());
        instream.close();

        Object controlObj = getReadControlObject();
        xmlToObjectTest(testObject, controlObj);
    }

    public void testObjectToResultWithTypeMappingInfoXML() throws Exception {

        Object objectToWrite = getWriteControlObject();
        XMLDescriptor desc = null;
        if (objectToWrite instanceof XMLRoot) {
            desc = (XMLDescriptor)((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext().getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
        } else {
            desc = (XMLDescriptor)((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext().getSession(0).getProject().getDescriptor(objectToWrite.getClass());
        }

        int sizeBefore = getNamespaceResolverSize(desc);
        StringWriter stringWriter = new StringWriter();
        StreamResult result = new StreamResult(stringWriter);
        jaxbMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/xml");

        ((JAXBMarshaller)jaxbMarshaller).marshal(objectToWrite, result, getTypeMappingInfo());

        int sizeAfter = getNamespaceResolverSize(desc);

        assertEquals(sizeBefore, sizeAfter);
        StringReader reader = new StringReader(stringWriter.toString());
        InputSource inputSource = new InputSource(reader);
        Document testDocument = parser.parse(inputSource);
        stringWriter.close();
        reader.close();
        objectToXMLDocumentTest(testDocument);
    }

    public void testObjectToXMLStreamWriterWithTypeMappingInfo() throws Exception {
        if(XML_OUTPUT_FACTORY != null) {
            StringWriter writer = new StringWriter();

            XMLOutputFactory factory = XMLOutputFactory.newInstance();
            factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.FALSE);
            XMLStreamWriter streamWriter= factory.createXMLStreamWriter(writer);

            Object objectToWrite = getWriteControlObject();
            XMLDescriptor desc = null;
            if (objectToWrite instanceof XMLRoot) {

                desc = (XMLDescriptor)((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext().getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
            } else {
                desc = (XMLDescriptor)((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext().getSession(0).getProject().getDescriptor(objectToWrite.getClass());
            }

            int sizeBefore = getNamespaceResolverSize(desc);
            ((JAXBMarshaller)jaxbMarshaller).marshal(objectToWrite, streamWriter, getTypeMappingInfo());

            streamWriter.flush();
            int sizeAfter = getNamespaceResolverSize(desc);

            assertEquals(sizeBefore, sizeAfter);
            StringReader reader = new StringReader(writer.toString());
            InputSource inputSource = new InputSource(reader);
            Document testDocument = parser.parse(inputSource);
            writer.close();
            reader.close();
            objectToXMLDocumentTest(testDocument);
        }
    }

    public void testObjectToXMLEventWriterWithTypeMappingInfo() throws Exception {
        if(XML_OUTPUT_FACTORY != null) {
            StringWriter writer = new StringWriter();

            XMLOutputFactory factory = XMLOutputFactory.newInstance();
            factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.FALSE);
            XMLEventWriter eventWriter= factory.createXMLEventWriter(writer);

            Object objectToWrite = getWriteControlObject();
            XMLDescriptor desc = null;
            if (objectToWrite instanceof XMLRoot) {
                desc = (XMLDescriptor)((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext().getSession(0).getProject().getDescriptor(((XMLRoot)objectToWrite).getObject().getClass());
            } else {
                desc = (XMLDescriptor)((org.eclipse.persistence.jaxb.JAXBContext)jaxbContext).getXMLContext().getSession(0).getProject().getDescriptor(objectToWrite.getClass());
            }

            int sizeBefore = getNamespaceResolverSize(desc);
            ((JAXBMarshaller)jaxbMarshaller).marshal(objectToWrite, eventWriter, getTypeMappingInfo());

            eventWriter.flush();
            int sizeAfter = getNamespaceResolverSize(desc);

            assertEquals(sizeBefore, sizeAfter);
            StringReader reader = new StringReader(writer.toString());
            InputSource inputSource = new InputSource(reader);
            Document testDocument = parser.parse(inputSource);
            writer.close();
            reader.close();
            objectToXMLDocumentTest(testDocument);
        }
    }

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

        JAXBElement controlObj = (JAXBElement)controlObject;
        JAXBElement testObj = (JAXBElement)testObject;
        compareJAXBElementObjects(controlObj, testObj);
    }

    public abstract Map<String, InputStream> getControlSchemaFiles();

    public void testSchemaGen() throws Exception {
        testSchemaGen(getControlSchemaFiles());
    }

     @Override
     protected void compareValues(Object controlValue, Object testValue){
         if(controlValue instanceof Node && testValue instanceof Node) {
             assertXMLIdentical(((Node)controlValue).getOwnerDocument(), ((Node)testValue).getOwnerDocument());
         } else if(controlValue instanceof DataHandler && testValue instanceof DataHandler){
             compareDataHandlers((DataHandler)controlValue, (DataHandler)testValue);
         } else if(controlValue instanceof Image && testValue instanceof Image) {
             compareImages((Image)controlValue, (Image) testValue);
         } else if (controlValue instanceof Byte[] && testValue instanceof Byte[]){
                compareByteArrays((Byte[])controlValue, (Byte[])testValue);
         } else if (controlValue instanceof byte[] && testValue instanceof byte[]){
                 compareByteArrays((byte[])controlValue, (byte[])testValue);
         } else {
             assertEquals(controlValue, testValue);
         }
     }

     private void compareDataHandlers(DataHandler controlValue, DataHandler testValue){
         assertEquals(controlValue.getContentType(), testValue.getContentType());
         try{
             assertEquals(controlValue.getContent(), testValue.getContent());
         }catch(Exception e){
              e.printStackTrace();
              fail();
          }
     }

     private void compareImages(Image controlImage, Image testImage) {
         assertEquals(controlImage.getWidth(null), testImage.getWidth(null));
         assertEquals(controlImage.getHeight(null), testImage.getHeight(null));
     }
       protected void setupParser() {
            try {
                DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
                builderFactory.setNamespaceAware(true);
                builderFactory.setIgnoringElementContentWhitespace(true);
                parser = builderFactory.newDocumentBuilder();
            } catch (Exception e) {
                e.printStackTrace();
                fail("An exception occurred during setup");
            }
        }

       public void setupControlDocs() throws Exception{
            if(this.controlDocumentLocation != null) {
                InputStream inputStream = ClassLoader.getSystemResourceAsStream(controlDocumentLocation);
                resourceName = controlDocumentLocation;
                controlDocument = parser.parse(inputStream);
                removeEmptyTextNodes(controlDocument);

                inputStream.close();
            }

        if(this.writeControlDocumentLocation != null) {
                InputStream inputStream = ClassLoader.getSystemResourceAsStream(writeControlDocumentLocation);
                writeControlDocument = parser.parse(inputStream);
                removeEmptyTextNodes(writeControlDocument);

                inputStream.close();
            }
        }
       protected int getNamespaceResolverSize(XMLDescriptor desc){
           int size = -1;
            if (desc != null) {
                NamespaceResolver nr = desc.getNamespaceResolver();
                if (nr != null) {
                    size = nr.getNamespaces().size();
                }else{
                  size =0;
                }
            }
            return size;
        }

       protected Document getControlDocument() {
            return controlDocument;
        }

        /**
         * Override this function to implement different read/write control documents.
         */
        protected Document getWriteControlDocument() throws Exception {
            if(writeControlDocument != null){
                return writeControlDocument;
            }
            return getControlDocument();
        }

        protected void setControlDocument(String xmlResource) throws Exception {
            this.controlDocumentLocation = xmlResource;
        }

        /**
         * Provide an alternative write version of the control document when rountrip is not enabled.
         * If this function is not called and getWriteControlDocument() is not overridden then the write and read control documents are the same.
         */
        protected void setWriteControlDocument(String xmlResource) throws Exception {
            writeControlDocumentLocation = xmlResource;
        }

        abstract protected Object getControlObject();
        /*
         * Returns the object to be used in a comparison on a read
         * This will typically be the same object used to write
         */
        public Object getReadControlObject() {
            return getControlObject();
        }

        /*
         * Returns the object to be written to XML which will be compared
         * to the control document.
         */
        public Object getWriteControlObject() {
            return getControlObject();
        }

        public void objectToXMLDocumentTest(Document testDocument) throws Exception {
            log("**objectToXMLDocumentTest**");
            log("Expected:");
            log(getWriteControlDocument());
            log("\nActual:");
            log(testDocument);
            assertXMLIdentical(getWriteControlDocument(), testDocument);
        }

        @Override
        public void compareJAXBElementObjects(JAXBElement controlObj, JAXBElement testObj) {
            assertEquals(controlObj.getName().getLocalPart(), testObj.getName().getLocalPart());
            assertEquals(controlObj.getName().getNamespaceURI(), testObj.getName().getNamespaceURI());
            assertEquals(controlObj.getDeclaredType(), testObj.getDeclaredType());

            Object controlValue = controlObj.getValue();
            Object testValue = testObj.getValue();

            if(controlValue == null) {
                if(testValue == null){
                    return;
                }
                fail("Test value should have been null");
            }else{
                if(testValue == null){
                    fail("Test value should not have been null");
                }
            }

            if(controlValue.getClass() == ClassConstants.ABYTE && testValue.getClass() == ClassConstants.ABYTE ||
                controlValue.getClass() == ClassConstants.APBYTE && testValue.getClass() == ClassConstants.APBYTE){
                compareValues(controlValue, testValue);
            }else if(controlValue.getClass().isArray()){
                if(testValue.getClass().isArray()){
                    if(controlValue.getClass().getComponentType().isPrimitive()){
                        comparePrimitiveArrays(controlValue, testValue);
                    }else{
                        compareObjectArrays(controlValue, testValue);
                    }
                }else{
                    fail("Expected an array value but was an " + testValue.getClass().getName());
                }
            }
            else if (controlValue instanceof Collection){
                Collection controlCollection = (Collection)controlValue;
                Collection testCollection = (Collection)testValue;
                Iterator<Object> controlIter = controlCollection.iterator();
                Iterator<Object> testIter = testCollection.iterator();
                assertEquals(controlCollection.size(), testCollection.size());
                while(controlIter.hasNext()){
                    Object nextControl = controlIter.next();
                    Object nextTest = testIter.next();
                    compareValues(nextControl, nextTest);
                }
            }else{
                compareValues(controlValue, testValue);
            }
        }

        protected void comparePrimitiveArrays(Object controlValue, Object testValue) {
            if (controlValue == null && testValue == null) {
                // equal
                return;
            }

            assertEquals(controlValue.getClass(), testValue.getClass());

            assertNotNull(controlValue);
            assertNotNull(testValue);

            int controlLength = Array.getLength(controlValue);
            int testLength = Array.getLength(controlValue);
            assertEquals(controlLength, testLength);

            for (int i = 0; i < controlLength; i++) {
                Object controlObject = Array.get(controlValue, i);
                Object testObject = Array.get(testValue, i);
                assertEquals(controlObject, testObject);
            }
        }

        protected void  compareObjectArrays(Object controlValue, Object testValue){
            assertEquals(((Object[])controlValue).length,((Object[])testValue).length);
            for(int i=0; i<((Object[])controlValue).length-1; i++){
                assertEquals(((Object[])controlValue)[i], ((Object[])testValue)[i]);
            }
        }

        public void testSchemaGen(Map<String, InputStream> controlSchemas) throws Exception {
            MyStreamSchemaOutputResolver outputResolver = new MyStreamSchemaOutputResolver();
            jaxbContext.generateSchema(outputResolver);

            Map<String, Writer> generatedSchemas = outputResolver.schemaFiles;
            assertEquals(controlSchemas.size(), generatedSchemas.size());

            for(String next:controlSchemas.keySet()){
                InputStream nextControlValue = controlSchemas.get(next);

                Writer sw = generatedSchemas.get(next);
                InputSource nextGeneratedValue = new InputSource(new StringReader(sw.toString()));

                assertNotNull("Generated Schema not found.", nextGeneratedValue);

                Document control = parser.parse(nextControlValue);
                Document test = parser.parse(nextGeneratedValue);

                JAXBXMLComparer xmlComparer = new JAXBXMLComparer();
                boolean isEqual = xmlComparer.isSchemaEqual(control, test);
                if(!isEqual){
                    log("Expected Schema\n");
                    log(control);
                    log("ActualSchema\n");
                    log(test);
                }
                assertTrue("generated schema did not match control schema", isEqual);
            }
        }

    /**
     * Return an Element for a given xml-element snippet.
     *
     */
    protected Element getXmlElement(String xmlelement) throws Exception {
        StringReader str = new StringReader(xmlelement);
        InputSource is = new InputSource(str);
        try {
            return parser.parse(is).getDocumentElement();
        } catch (Exception e) {
            throw e;
        }
    }

    private boolean compareByteArrays(Byte[] first, Byte[] second){
        if(first.length != second.length){
            return false;
        }

        for(int i=0; i<first.length; i++){
            if (first[i] != second[i]){
                return false;
            }
        }
        return true;
    }

     private boolean compareByteArrays(byte[] first, byte[] second){
        if(first.length != second.length){
            return false;
        }

        for(int i=0; i<first.length; i++){
            if (first[i] != second[i]){
                return false;
            }
        }
        return true;
    }

    protected void validateBindingsFileAgainstSchema(Source src) {
         String result = null;
         SchemaFactory sFact = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
         Schema theSchema;
         try {
             theSchema = sFact.newSchema(bindingsFileXSDSource);
             Validator validator = theSchema.newValidator();

             validator.validate(src);
         } catch (Exception e) {
             e.printStackTrace();
             if (e.getMessage() == null) {
                 result = "An unknown exception occurred.";
             }
             result = e.getMessage();
         }
         assertTrue("Schema validation failed unxepectedly: " + result, result == null);
     }

    public static class MyStreamSchemaOutputResolver extends SchemaOutputResolver {
        // keep a list of processed schemas for the validation phase of the test(s)
        public Map<String, Writer> schemaFiles;

        public MyStreamSchemaOutputResolver() {
            schemaFiles = new HashMap<String, Writer>();
        }

        @Override
        public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
            //return new StreamResult(System.out);
            if (namespaceURI == null) {
                namespaceURI = "";
            }

            StringWriter sw = new StringWriter();
            schemaFiles.put(namespaceURI, sw);
            Result res = new StreamResult(sw);
            res.setSystemId(suggestedFileName);
            return res;
        }
    }
}





