/*
 * Copyright (c) 2011, 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:
//     Blaise Doughan - 2.2 - initial implementation
package org.eclipse.persistence.jaxb.dynamic.metadata;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jakarta.xml.bind.JAXBException;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaModelInput;
import org.eclipse.persistence.jaxb.javamodel.xjc.XJCJavaClassImpl;
import org.eclipse.persistence.jaxb.javamodel.xjc.XJCJavaModelImpl;
import org.eclipse.persistence.jaxb.javamodel.xjc.XJCJavaModelInputImpl;
import org.eclipse.persistence.platform.xml.XMLPlatformException;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.platform.xml.XMLTransformer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;

import com.sun.codemodel.ClassType;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JEnumConstant;
import com.sun.codemodel.JPackage;
import com.sun.tools.xjc.Plugin;
import com.sun.tools.xjc.api.ErrorListener;
import com.sun.tools.xjc.api.S2JJAXBModel;
import com.sun.tools.xjc.api.SchemaCompiler;
import com.sun.tools.xjc.api.XJC;

public class SchemaMetadata extends Metadata {

    private static final String DEFAULT_SYSTEM_ID = "sysid";

    private SchemaCompiler schemaCompiler;

    private List<InputSource> externalBindings;

    @SuppressWarnings("unchecked")
    public SchemaMetadata(DynamicClassLoader dynamicClassLoader, Map<String, Object> properties) throws JAXBException {
        super(dynamicClassLoader, properties);

        try {
            if (properties != null) {
                Object propValue = properties.get(DynamicJAXBContextFactory.EXTERNAL_BINDINGS_KEY);
                if (propValue != null) {
                    externalBindings = new ArrayList<>();
                    if (propValue instanceof List<?>) {
                        List<Source> xjbSources = (List<Source>) propValue;
                        for (Source source : xjbSources) {
                            externalBindings.add(createInputSourceFromSource(source));
                        }
                    } else {
                        Source xjbSource = (Source) propValue;
                        InputSource xjbInputSource = createInputSourceFromSource(xjbSource);
                        externalBindings.add(xjbInputSource);
                    }
                }
            }
        } catch (ClassCastException cce) {
            throw new JAXBException(org.eclipse.persistence.exceptions.JAXBException.xjbNotSource());
        }


    }

    public SchemaMetadata(DynamicClassLoader dynamicClassLoader, Map<String, Object> properties, Source metadataSource, EntityResolver resolver) throws JAXBException {
        this(dynamicClassLoader, properties);
        try {
            InputSource schemaInputSource = createInputSourceFromSource(metadataSource);

            if (schemaInputSource.getSystemId() == null) {
                schemaInputSource.setSystemId(DEFAULT_SYSTEM_ID);
            }

            // Use XJC API to parse the schema and generate its JCodeModel
            schemaCompiler = XJC.createSchemaCompiler();
            schemaCompiler.setEntityResolver(resolver);
            schemaCompiler.setErrorListener(new XJCErrorListener());

            if (externalBindings != null) {
                for (InputSource xjbSource : externalBindings) {
                    schemaCompiler.parseSchema(xjbSource);
                }
            }

            schemaCompiler.parseSchema(schemaInputSource);
        } catch (XMLPlatformException xpe) {
            // This will occur when trying to refreshMetadata from a closed stream (non-XML Node metadata)
            if (xpe.getCause() instanceof TransformerException) {
                TransformerException te = (TransformerException) xpe.getCause();
                if (te.getCause() instanceof IOException) {
                    throw org.eclipse.persistence.exceptions.JAXBException.cannotRefreshMetadata();
                }
            }
        } catch (Exception e) {
            throw new JAXBException(org.eclipse.persistence.exceptions.JAXBException.errorCreatingDynamicJAXBContext(e));
        }
    }

    public SchemaMetadata(DynamicClassLoader dynamicClassLoader, Map<String, Object> properties, Node node, EntityResolver resolver) throws JAXBException {
        this(dynamicClassLoader, properties);

        Element element;
        if (node.getNodeType() == Node.DOCUMENT_NODE) {
            element = ((Document) node).getDocumentElement();
        } else if (node.getNodeType() == Node.ELEMENT_NODE) {
            element = (Element) node;
        } else {
            throw new JAXBException(org.eclipse.persistence.exceptions.JAXBException.cannotInitializeFromNode());
        }

        // Use XJC API to parse the schema and generate its JCodeModel
        schemaCompiler = XJC.createSchemaCompiler();
        schemaCompiler.setEntityResolver(resolver);
        schemaCompiler.setErrorListener(new XJCErrorListener());
        schemaCompiler.parseSchema(DEFAULT_SYSTEM_ID, element);
    }

    @Override
    public JavaModelInput getJavaModelInput() throws JAXBException {
        S2JJAXBModel model = schemaCompiler.bind();

        if (model == null) {
            throw new JAXBException(org.eclipse.persistence.exceptions.JAXBException.xjcBindingError());
        }

        JCodeModel codeModel = model.generateCode(new Plugin[0], null);

        // Create EclipseLink JavaModel objects for each of XJC's JDefinedClasses
        ArrayList<JDefinedClass> classesToProcess = new ArrayList<>();
        Iterator<JPackage> packages = codeModel.packages();
        while (packages.hasNext()) {
            JPackage pkg = packages.next();
            Iterator<JDefinedClass> classes = pkg.classes();
            while (classes.hasNext()) {
                JDefinedClass cls = classes.next();
                classesToProcess.add(cls);
            }
        }

        // Look for Inner Classes and add them
        ArrayList<JDefinedClass> innerClasses = new ArrayList<>();
        for (int i = 0; i < classesToProcess.size(); i++) {
            innerClasses.addAll(getInnerClasses(classesToProcess.get(i)));
        }
        classesToProcess.addAll(innerClasses);

        JavaClass[] jotClasses = createClassModelFromXJC(classesToProcess, codeModel, dynamicClassLoader);

        // Use the JavaModel to setup a Generator to generate an EclipseLink project
        XJCJavaModelImpl javaModel = new XJCJavaModelImpl(codeModel, dynamicClassLoader);
        XJCJavaModelInputImpl javaModelInput = new XJCJavaModelInputImpl(jotClasses, javaModel);

        for (JavaClass javaClass : jotClasses) {
            ((XJCJavaClassImpl) javaClass).setJavaModel(javaModel);
            javaModel.getJavaModelClasses().put(javaClass.getQualifiedName(), javaClass);
        }

        return javaModelInput;
    }

    private HashSet<JDefinedClass> getInnerClasses(JDefinedClass xjcClass) {
        // Check this xjcClass for inner classes.  If one is found, search that one too.

        HashSet<JDefinedClass> classesToReturn = new HashSet<>();
        Iterator<JDefinedClass> it = xjcClass.classes();

        while (it.hasNext()) {
            JDefinedClass innerClass = it.next();
            classesToReturn.add(innerClass);
            classesToReturn.addAll(getInnerClasses(innerClass));
        }

        return classesToReturn;
    }

    @SuppressWarnings("unchecked")
    private JavaClass[] createClassModelFromXJC(ArrayList<JDefinedClass> xjcClasses, JCodeModel jCodeModel, DynamicClassLoader dynamicClassLoader) throws JAXBException {
        try {
            JavaClass[] elinkClasses = new JavaClass[xjcClasses.size()];

            int count = 0;
            for (JDefinedClass definedClass : xjcClasses) {
                XJCJavaClassImpl xjcClass = new XJCJavaClassImpl(definedClass, jCodeModel, dynamicClassLoader);
                elinkClasses[count] = xjcClass;
                count++;

                // If this is an enum, trigger a dynamic class generation, because we won't
                // be creating a descriptor for it
                if (definedClass.getClassType().equals(ClassType.ENUM)) {
                    Map<String, JEnumConstant> enumConstants = definedClass.enumConstants();
                    Object[] enumValues = enumConstants.keySet().toArray();
                    dynamicClassLoader.addEnum(definedClass.fullName(), enumValues);
                }
            }

            return elinkClasses;
        } catch (Exception e) {
            throw new JAXBException(org.eclipse.persistence.exceptions.JAXBException.errorCreatingDynamicJAXBContext(e));
        }
    }

    private static InputSource createInputSourceFromSource(Source aSource) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        StreamResult result = new StreamResult(baos);
        XMLTransformer t = XMLPlatformFactory.getInstance().getXMLPlatform().newXMLTransformer();
        t.transform(aSource, result);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        InputSource inputSource = new InputSource(bais);
        inputSource.setSystemId(aSource.getSystemId());

        return inputSource;
    }

    private class XJCErrorListener implements ErrorListener {

        @Override
        public void error(SAXParseException arg0) {
            throw org.eclipse.persistence.exceptions.JAXBException.errorCreatingDynamicJAXBContext(arg0);
        }

        @Override
        public void fatalError(SAXParseException arg0) {
            throw org.eclipse.persistence.exceptions.JAXBException.errorCreatingDynamicJAXBContext(arg0);
        }

        @Override
        public void info(SAXParseException arg0) {
            throw org.eclipse.persistence.exceptions.JAXBException.errorCreatingDynamicJAXBContext(arg0);
        }

        @Override
        public void warning(SAXParseException arg0) {
            throw org.eclipse.persistence.exceptions.JAXBException.errorCreatingDynamicJAXBContext(arg0);
        }

    }

}
