/*
 * 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.oxm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Iterator;
import java.util.TimeZone;

import jakarta.xml.bind.JAXBElement;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLLogin;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.platform.DOMPlatform;
import org.eclipse.persistence.oxm.platform.SAXPlatform;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.factories.MissingDescriptorListener;
import org.eclipse.persistence.internal.sessions.factories.ObjectPersistenceRuntimeXMLProject_11_1_1;
import org.eclipse.persistence.sessions.factories.SessionManager;
import org.eclipse.persistence.sessions.factories.XMLProjectReader;
import org.eclipse.persistence.sessions.factories.XMLProjectWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public abstract class OXTestCase extends XMLTestCase {
    protected static XMLInputFactory XML_INPUT_FACTORY;
    protected static XMLOutputFactory XML_OUTPUT_FACTORY;
    protected static Class staxResultClass;
    protected static String staxResultClassName = "javax.xml.transform.stax.StAXResult";
    protected static Class staxSourceClass;
    protected static String staxSourceClassName = "javax.xml.transform.stax.StAXSource";
    protected static Constructor staxResultStreamWriterConstructor;
    protected static Constructor staxResultEventWriterConstructor;
    protected static Constructor staxSourceStreamReaderConstructor;
    protected static Constructor staxSourceEventReaderConstructor;

    protected static final String TIMEZONE_OFFSET;

    static {
        try {
            XML_INPUT_FACTORY = XMLInputFactory.newInstance();
            XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance();
        } catch(javax.xml.stream.FactoryConfigurationError error){
            XML_INPUT_FACTORY = null;
            XML_OUTPUT_FACTORY = null;
        }
        try {
            staxResultClass = PrivilegedAccessHelper.getClassForName(staxResultClassName);
            staxResultStreamWriterConstructor = PrivilegedAccessHelper.getConstructorFor(staxResultClass, new Class[]{XMLStreamWriter.class}, true);
            staxResultEventWriterConstructor = PrivilegedAccessHelper.getConstructorFor(staxResultClass, new Class[]{XMLEventWriter.class}, true);
        } catch(Exception ex) {
            staxResultClass = null;
        }

        try {
            staxSourceClass = PrivilegedAccessHelper.getClassForName(staxSourceClassName);
            staxSourceStreamReaderConstructor = PrivilegedAccessHelper.getConstructorFor(staxSourceClass, new Class[]{XMLStreamReader.class}, true);
            staxSourceEventReaderConstructor = PrivilegedAccessHelper.getConstructorFor(staxSourceClass, new Class[]{XMLEventReader.class}, true);
        } catch(Exception ex) {
            staxSourceClass = null;
        }

        // Bug #454154 and #453330
        // DateAndTime tests are susceptible to changes in time zone. And since they were not written to support
        // GMT+00:00 time zone, which in Java translates to "Z" short-hand,
        // and since further complications arise from the fact that TIME_OFFSET is computed only once per OXTestCase
        // class and without having any information about daylight savings offset,
        // some tests were failing under GMT+00:00 Time Zone.
        // There are 2 options for how to solve this problem now: do massive rewrite of all DateAndTime tests or use a
        // time zone that does not cause problems. Second option has been chosen for now.
        TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));

        int offsetInMillis = TimeZone.getDefault().getRawOffset();
        String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000), Math.abs((offsetInMillis / 60000) % 60));
        TIMEZONE_OFFSET = offsetInMillis == 0 ? "Z" : ((offsetInMillis >= 0 ? "+" : "-") + offset);
    }

    public boolean useLogging = false;
    public static enum Platform { DOM, SAX, DOC_PRES };
    public static enum Metadata { JAVA, XML_TOPLINK, XML_ECLIPSELINK };
    public static Platform platform;;
    public static Metadata metadata;
    // Constants
    public static final String PLATFORM_KEY = "platformType";
    public static final String PLATFORM_DOM = "DOM";
    public static final String PLATFORM_DOC_PRES = "DOC_PRES";
    public static final String PLATFORM_SAX = "SAX";
    public static final String METADATA_KEY = "metadataType";
    public static final String METADATA_JAVA = "JAVA";
    public static final String METADATA_TOPLINK = "XML_TOPLINK";
    public static final String METADATA_XML_ECLIPSELINK = "XML_ECLIPSELINK";

    public OXTestCase(String name) {
        super(name);
        useLogging = Boolean.getBoolean("useLogging");
        platform = getPlatform();
        metadata = getMetadata();
    }

    public XMLContext getXMLContext(String name) {
        Session session = SessionManager.getManager().getSession(name, false);
        Project project = session.getProject();
        return getXMLContext(project);
    }

    public XMLContext getXMLContext(Project project) {
        if (platform == Platform.DOC_PRES) {
            Collection<ClassDescriptor> descriptors = project.getDescriptors().values();
            Iterator<ClassDescriptor> iter = descriptors.iterator();
            while (iter.hasNext()) {
                ClassDescriptor nextDesc = iter.next();
                if (nextDesc instanceof org.eclipse.persistence.oxm.XMLDescriptor) {
                    ((org.eclipse.persistence.oxm.XMLDescriptor)nextDesc).setShouldPreserveDocument(true);
                }
            }
        }

        Project newProject = this.getNewProject(project, null);
        return new XMLContext(newProject);
    }

    public XMLContext getXMLContext(Project project, ClassLoader classLoader) {
        ConversionManager.getDefaultManager().setLoader(classLoader);
        Project newProject = this.getNewProject(project, classLoader);
        newProject.getDatasourceLogin().getDatasourcePlatform().getConversionManager().setLoader(classLoader);
        return new XMLContext(newProject);
    }

    public Project getNewProject(Project originalProject) {
        return getNewProject(originalProject, null);
    }

    public Project getNewProject(Project originalProject, ClassLoader classLoader) {
        Project newProject = originalProject;

        switch (metadata) {
            case JAVA:
                break;
            default:
                try {
                    // Write the deployment XML file to deploymentXML-file.xml
                    String fileName = "deploymentXML-file.xml";
                    FileWriter fWriter = new FileWriter(fileName);
                    write(originalProject, fWriter);
                    fWriter.close();
                    // Also write the deployment XML file to a stringwriter for logging
                    if (useLogging) {
                        StringWriter stringWriter = new StringWriter();
                        write(originalProject, stringWriter);
                        log("DEPLOYMENT XML " + stringWriter.toString());
                    }
                    // Read the deploymentXML-file.xml back in with XMLProjectReader
                    FileInputStream inStream = new FileInputStream(fileName);
                    FileReader fileReader = new FileReader(fileName);
                    newProject = XMLProjectReader.read(fileReader, classLoader);
                    inStream.close();
                    fileReader.close();
                    File f = new File(fileName);
                    f.delete();
                } catch (Exception e) {
                    e.printStackTrace();
                    StringWriter stringWriter = new StringWriter();
                    write(originalProject, stringWriter);
                    StringReader reader = new StringReader(stringWriter.toString());
                    log("DEPLOYMENT XML" + stringWriter.toString());
                    newProject = XMLProjectReader.read(reader, classLoader);
                }
        }

        if ((newProject.getDatasourceLogin() == null) || (!(newProject.getDatasourceLogin() instanceof XMLLogin))) {
            newProject.setDatasourceLogin(new XMLLogin());
        }

        switch (platform) {
            case SAX:
                newProject.getDatasourceLogin().setPlatform(new SAXPlatform());
                break;
            default:
                newProject.getDatasourceLogin().setPlatform(new DOMPlatform());
        }
        return newProject;
    }

    protected void log(Document document) {
        if (!useLogging) {
            return;
        }

        try {
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result = new StreamResult(System.out);
            transformer.transform(source, result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void log(String string) {
        if (useLogging) {
            System.out.println(string);
        }
    }

    protected void log(byte[] bytes) {
        if (useLogging) {
            for (int i = 0; i < bytes.length; i++) {
                System.out.print(bytes[i]);
            }
        }
    }

    @Override
    public String getName() {
        String longClassName = this.getClass().getName();
        String shortClassName = longClassName.substring(longClassName.lastIndexOf(".") + 1, longClassName.length() - 1);
        String description = "";

        switch (metadata) {
            case XML_ECLIPSELINK:
                description = "Deployment XML w/";
                break;
            case XML_TOPLINK:
                description = "TL Deployment XML w/";
                break;
            default:
                description = "Java Project Source w/";
        }

        switch (platform) {
            case DOC_PRES:
                description += "Doc Pres: ";
                break;
            case DOM:
                description += "DOM Parsing: ";
                break;
            default:
                description += "SAX Parsing: ";
        }

        return description + shortClassName + ": " + super.getName();
    }

    public static void removeEmptyTextNodes(Node node) {
        NodeList nodeList = node.getChildNodes();
        Node childNode;
        for (int x = nodeList.getLength() - 1; x >= 0; x--) {
            childNode = nodeList.item(x);
            if (childNode.getNodeType() == Node.TEXT_NODE) {
                if (childNode.getNodeValue().trim().equals("")) {
                    node.removeChild(childNode);
                }
            } else if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                removeEmptyTextNodes(childNode);
            }
        }
    }

    public static void removeCopyrightNode(Node node) {
        NodeList nodeList = node.getChildNodes();
        Node childNode;
        for (int x = 0; x < nodeList.getLength(); x++) {
            childNode = nodeList.item(x);
            if (childNode.getNodeType() == Node.COMMENT_NODE) {
                if (childNode.getNodeValue().trim().contains("Copyright")) {
                    node.removeChild(childNode);
                    break;
                }
            }
        }
    }

    public static String removeWhiteSpaceFromString(String s) {
        String returnString = s.replaceAll(" ", "");
        returnString = returnString.replaceAll("\n", "");
        returnString = returnString.replaceAll("\t", "");
        returnString = returnString.replaceAll("\r", "");

        return returnString;
    }

    public static String removeCopyrightFromString(String s) {
        return s.replaceAll("<!--.*Copyright.*?-->", "");
    }

    /**
     * Return the Platform to be used based on the "platformType"
     * System property
     *
     * @see Platform
     */
    public Platform getPlatform() {
        String platformStr = System.getProperty(PLATFORM_KEY, PLATFORM_SAX);
        if (platformStr.equals(PLATFORM_SAX)) {
            return Platform.SAX;
        }
        if (platformStr.equals(PLATFORM_DOM)) {
            return Platform.DOM;
        }
        return Platform.DOC_PRES;
    }

    /**
     * Return the Metadata type based on the "metadataType"
     * System property
     *
     * @see Metadata
     */
    public Metadata getMetadata() {
        String metadataStr = System.getProperty(METADATA_KEY, METADATA_JAVA);
        if (metadataStr.equals(METADATA_JAVA)) {
            return Metadata.JAVA;
        }
        if (metadataStr.equals(METADATA_XML_ECLIPSELINK)) {
            return Metadata.XML_ECLIPSELINK;
        }
        return Metadata.XML_TOPLINK;
    }

    // Write out deployment XML
    public void write(Project project, Writer writer) {
        // Write out EclipseLink deployment XML
        if (metadata == Metadata.XML_ECLIPSELINK) {
            XMLProjectWriter.write(project, writer);
            return;
        }
        // Write out TL deployment XML
        XMLContext context = new XMLContext(new ObjectPersistenceRuntimeXMLProject_11_1_1());
        context.getSession(project).getEventManager().addListener(new MissingDescriptorListener());
        XMLMarshaller marshaller = context.createMarshaller();
        marshaller.marshal(project, writer);
        try {
            writer.flush();
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
    }

    public void compareJAXBElementObjects(JAXBElement controlObj, JAXBElement testObj) {
        compareJAXBElementObjects(controlObj, testObj, true);
    }
    public void compareJAXBElementObjects(JAXBElement controlObj, JAXBElement testObj, boolean namespaceAware) {
        assertEquals(controlObj.getName().getLocalPart(), testObj.getName().getLocalPart());
        if(namespaceAware){
            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().isArray()){
            compareArrays(controlValue, testValue);
        }
        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.getClass(), testCollection.getClass());
            assertEquals(controlCollection.size(), testCollection.size());
            while(controlIter.hasNext()){
                Object nextControl = controlIter.next();
                Object nextTest = testIter.next();
                compareValues(nextControl, nextTest);
            }
        }else{
            compareValues(controlValue, testValue);
        }
    }

    @Override
    protected void compareValues(Object controlValue, Object testValue){
        if(controlValue instanceof JAXBElement && testValue instanceof JAXBElement){
            compareJAXBElementObjects((JAXBElement)controlValue, (JAXBElement)testValue);
        }else{
            super.compareValues(controlValue, testValue);
        }
    }

    protected String loadFileToString(String fileName){
        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
        return loadInputStreamToString(inputStream);
    }

    protected String loadInputStreamToString(InputStream inputStream){
        StringBuilder sb = new StringBuilder();
        String lineSep = System.getProperty("line.separator");

        try {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str;
            //Don't add the lineSep the first time
            if(bufferedReader.ready()){
                sb.append(bufferedReader.readLine());
            }
            while (bufferedReader.ready()) {
                sb.append(lineSep);
                sb.append(bufferedReader.readLine());
            }
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            fail();
        }
        return sb.toString();
    }
}
