/*
 * Copyright (c) 2019, 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.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.wadl.doclet;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ResourceDocType;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

class DocletUtils {

    private static final Logger LOG = Logger.getLogger(DocletUtils.class.getName());

    private static String[] getCDataElements(DocProcessor docProcessor) {
        String[] original = new String[]{"commentText"};
        if (docProcessor == null) {
            return original;
        } else {
            String[] cdataElements = docProcessor.getCDataElements();
            if (cdataElements == null || cdataElements.length == 0) {
                return original;
            } else {

                String[] result = copyOf(original, original.length + cdataElements.length);
                for (int i = 0; i < cdataElements.length; i++) {
                    result[original.length + i] = cdataElements[i];
                }
                return result;
            }
        }
    }

    @SuppressWarnings("unchecked")
    private static <T, U> T[] copyOf(U[] original, int newLength) {
        T[] copy = (original.getClass() == Object[].class) ? (T[]) new Object[newLength]
                : (T[]) Array.newInstance(original.getClass().getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
        return copy;
    }

    private static Class<?>[] getJAXBContextClasses(ResourceDocType result, DocProcessor docProcessor) {
        Class<?>[] clazzes;
        if (docProcessor == null) {
            clazzes = new Class<?>[1];
        } else {
            Class<?>[] requiredJaxbContextClasses = docProcessor.getRequiredJaxbContextClasses();
            if (requiredJaxbContextClasses != null) {
                clazzes = new Class<?>[1 + requiredJaxbContextClasses.length];
                for (int i = 0; i < requiredJaxbContextClasses.length; i++) {
                    clazzes[i + 1] = requiredJaxbContextClasses[i];
                }
            } else {
                clazzes = new Class<?>[1];
            }
        }
        clazzes[0] = result.getClass();
        return clazzes;
    }

    static boolean createOutputFile(String filePath, DocProcessor docProcessor, ResourceDocType result) {
        String[] cdataElements = getCDataElements(docProcessor);
        Class<?>[] classes = getJAXBContextClasses(result, docProcessor);
        LOG.info("cdataElements " + Arrays.asList(cdataElements));
        LOG.info("classes " + Arrays.asList(classes));
        try (OutputStream out = new BufferedOutputStream(new FileOutputStream(filePath))) {
            JAXBContext c = JAXBContext.newInstance(classes);
            Marshaller m = c.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            StringWriter sw = new StringWriter();
            // Produces XML in memory
            m.marshal(result, sw);
            // Loads the XML from memory for processing
            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                    .parse(new ByteArrayInputStream(sw.toString().getBytes()));
            for (String cdata : cdataElements) {
                NodeList nodes = document.getElementsByTagName(cdata);
                LOG.info(nodes.getLength() + " nodes found by " + cdata);
                for (int i = 0; i < nodes.getLength(); i++) {
                    Node node = nodes.item(i);
                    CDATASection cdataSection = document.createCDATASection(node.getTextContent());
                    // Remove current content
                    node.setTextContent(null);
                    // Add it again, but wrapped with CDATA
                    node.appendChild(cdataSection);
                }
                document.createCDATASection(cdata);
            }
            DOMSource source = new DOMSource(document);
            StreamResult streamResult = new StreamResult(out);
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.transform(source, streamResult);
            LOG.info("Wrote " + result + " in " + filePath);
            return true;
        } catch (Exception e) {
            LOG.log(Level.SEVERE, "Could not serialize ResourceDoc.", e);
            return false;
        }
    }

    static String getLinkClass(String className, String field) {
        Object object;
        try {
            Field declaredField = Class.forName(className, false, Thread.currentThread()
                    .getContextClassLoader()).getDeclaredField(field);
            declaredField.setAccessible(true);
            object = declaredField.get(null);
            LOG.log(Level.FINE, "Got object " + object);
        } catch (final Exception e) {
            LOG.info("Have classloader: " + ResourceDoclet.class.getClassLoader().getClass());
            LOG.info("Have thread classloader " + Thread.currentThread().getContextClassLoader().getClass());
            LOG.info("Have system classloader " + ClassLoader.getSystemClassLoader().getClass());
            LOG.log(Level.SEVERE, "Could not get field " + className, e);
            return null;
        }

        /* marshal the bean to xml
         */
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
            StringWriter stringWriter = new StringWriter();
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(object, stringWriter);
            String result = stringWriter.getBuffer().toString();
            LOG.log(Level.FINE, "Got marshalled output:\n" + result);
            return result;
        } catch (final Exception e) {
            LOG.log(Level.SEVERE, "Could serialize bean to xml: " + object, e);
            return null;
        }
    }

}
