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

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(JAXBContextProperties.OXM_METADATA_SOURCE);
            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;
        }
    }
}





