/*
 * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.glassfish.jaxb.runtime.v2;

import com.sun.istack.FinalArrayList;
import org.glassfish.jaxb.core.Utils;
import org.glassfish.jaxb.runtime.api.JAXBRIContext;
import org.glassfish.jaxb.runtime.api.TypeReference;
import org.glassfish.jaxb.runtime.v2.model.annotation.RuntimeAnnotationReader;
import org.glassfish.jaxb.core.v2.Messages;
import org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl;
import org.glassfish.jaxb.runtime.v2.util.TypeCast;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.logging.Level;

/**
 * This class is responsible for producing RI JAXBContext objects.
 *
 * <p>
 * Used to create JAXBContext objects for v1.0.1 and forward
 *
 * @since 2.0
 * @author Kohsuke Kawaguchi
 */
public class ContextFactory {

    /**
     * Private constructor.
     */
    private ContextFactory() {}

    /**
     * The API will invoke this method via reflection
     */
    public static JAXBContext createContext(Class[] classes, Map<String,Object> properties ) throws JAXBException {
        MUtils.open(classes);
        // fool-proof check, and copy the map to make it easier to find unrecognized properties.
        if(properties==null)
            properties = Collections.emptyMap();
        else
            properties = new HashMap<>(properties);

        String defaultNsUri = getPropertyValue(properties, JAXBRIContext.DEFAULT_NAMESPACE_REMAP,String.class);

        Boolean c14nSupport = getPropertyValue(properties,JAXBRIContext.CANONICALIZATION_SUPPORT,Boolean.class);
        if(c14nSupport==null)
            c14nSupport = false;

        Boolean disablesecurityProcessing = getPropertyValue(properties, JAXBRIContext.DISABLE_XML_SECURITY, Boolean.class);
        if (disablesecurityProcessing==null)
            disablesecurityProcessing = false;

        Boolean allNillable = getPropertyValue(properties,JAXBRIContext.TREAT_EVERYTHING_NILLABLE,Boolean.class);
        if(allNillable==null)
            allNillable = false;

        Boolean retainPropertyInfo = getPropertyValue(properties, JAXBRIContext.RETAIN_REFERENCE_TO_INFO, Boolean.class);
        if(retainPropertyInfo==null)
            retainPropertyInfo = false;

        Boolean supressAccessorWarnings = getPropertyValue(properties, JAXBRIContext.SUPRESS_ACCESSOR_WARNINGS, Boolean.class);
        if(supressAccessorWarnings==null)
            supressAccessorWarnings = false;

        Boolean improvedXsiTypeHandling = getPropertyValue(properties, JAXBRIContext.IMPROVED_XSI_TYPE_HANDLING, Boolean.class);
        if (improvedXsiTypeHandling == null) {
            String improvedXsiSystemProperty = Utils.getSystemProperty(JAXBRIContext.IMPROVED_XSI_TYPE_HANDLING);
            if (improvedXsiSystemProperty == null) {
                improvedXsiTypeHandling = true;
            } else {
                improvedXsiTypeHandling = Boolean.valueOf(improvedXsiSystemProperty);
            }
        }

        Boolean xmlAccessorFactorySupport = getPropertyValue(properties,
           JAXBRIContext.XMLACCESSORFACTORY_SUPPORT,Boolean.class);
        if(xmlAccessorFactorySupport==null){
            xmlAccessorFactorySupport = false;
            Utils.getClassLogger().log(Level.FINE, "Property " +
                JAXBRIContext.XMLACCESSORFACTORY_SUPPORT +
                "is not active.  Using JAXB's implementation");
        }

        Boolean backupWithParentNamespace = getPropertyValue(properties, JAXBRIContext.BACKUP_WITH_PARENT_NAMESPACE, Boolean.class);

        RuntimeAnnotationReader ar = getPropertyValue(properties,JAXBRIContext.ANNOTATION_READER,RuntimeAnnotationReader.class);

        Collection<TypeReference> tr = getPropertyValue(properties, JAXBRIContext.TYPE_REFERENCES, Collection.class);
        if (tr == null) {
            tr = Collections.emptyList();
        }

        Map<Class,Class> subclassReplacements;
        try {
            subclassReplacements = TypeCast.checkedCast(
                getPropertyValue(properties, JAXBRIContext.SUBCLASS_REPLACEMENTS, Map.class), Class.class, Class.class);
        } catch (ClassCastException e) {
            throw new JAXBException(Messages.INVALID_TYPE_IN_MAP.format(),e);
        }

        Integer maxErrorsCount = getPropertyValue(properties, JAXBRIContext.MAX_ERRORS, Integer.class);
        if (maxErrorsCount == null) {
            maxErrorsCount = 10;
        } else if (maxErrorsCount < 0) {
            // negative value means unlimited number of reported errors
            maxErrorsCount = Integer.MAX_VALUE;
        }

        if(!properties.isEmpty()) {
            throw new JAXBException(Messages.UNSUPPORTED_PROPERTY.format(properties.keySet().iterator().next()));
        }

        JAXBContextImpl.JAXBContextBuilder builder = new JAXBContextImpl.JAXBContextBuilder();
        builder.setClasses(classes);
        builder.setTypeRefs(tr);
        builder.setSubclassReplacements(subclassReplacements);
        builder.setDefaultNsUri(defaultNsUri);
        builder.setC14NSupport(c14nSupport);
        builder.setAnnotationReader(ar);
        builder.setXmlAccessorFactorySupport(xmlAccessorFactorySupport);
        builder.setAllNillable(allNillable);
        builder.setRetainPropertyInfo(retainPropertyInfo);
        builder.setSupressAccessorWarnings(supressAccessorWarnings);
        builder.setImprovedXsiTypeHandling(improvedXsiTypeHandling);
        builder.setDisableSecurityProcessing(disablesecurityProcessing);
        builder.setBackupWithParentNamespace(backupWithParentNamespace);
        builder.setMaxErrorsCount(maxErrorsCount);
        return builder.build();
    }

    /**
     * If a key is present in the map, remove the value and return it.
     */
    private static <T> T getPropertyValue(Map<String, Object> properties, String keyName, Class<T> type ) throws JAXBException {
        Object o = properties.get(keyName);
        if(o==null)     return null;

        properties.remove(keyName);
        if(!type.isInstance(o))
            throw new JAXBException(Messages.INVALID_PROPERTY_VALUE.format(keyName,o));
        else
            return type.cast(o);
    }

    /**
     *
     * @deprecated use {@code createContext(Class[] classes, Map<String,Object> properties)} method instead
     */
    @Deprecated
    public static JAXBRIContext createContext( Class[] classes,
            Collection<TypeReference> typeRefs, Map<Class,Class> subclassReplacements,
            String defaultNsUri, boolean c14nSupport, RuntimeAnnotationReader ar,
            boolean xmlAccessorFactorySupport, boolean allNillable, boolean retainPropertyInfo) throws JAXBException {

        return createContext(classes, typeRefs, subclassReplacements,
                defaultNsUri, c14nSupport, ar, xmlAccessorFactorySupport,
                allNillable, retainPropertyInfo, false);
    }

    /**
     *
     * @deprecated use {@code createContext( Class[] classes, Map<String,Object> properties)} method instead
     */
    @Deprecated
    public static JAXBRIContext createContext( Class[] classes,
            Collection<TypeReference> typeRefs, Map<Class,Class> subclassReplacements,
            String defaultNsUri, boolean c14nSupport, RuntimeAnnotationReader ar,
            boolean xmlAccessorFactorySupport, boolean allNillable, boolean retainPropertyInfo, boolean improvedXsiTypeHandling) throws JAXBException {
        MUtils.open(classes);

        JAXBContextImpl.JAXBContextBuilder builder = new JAXBContextImpl.JAXBContextBuilder();
        builder.setClasses(classes);
        builder.setTypeRefs(typeRefs);
        builder.setSubclassReplacements(subclassReplacements);
        builder.setDefaultNsUri(defaultNsUri);
        builder.setC14NSupport(c14nSupport);
        builder.setAnnotationReader(ar);
        builder.setXmlAccessorFactorySupport(xmlAccessorFactorySupport);
        builder.setAllNillable(allNillable);
        builder.setRetainPropertyInfo(retainPropertyInfo);
        builder.setImprovedXsiTypeHandling(improvedXsiTypeHandling);
        return builder.build();
    }

    /**
     * The API will invoke this method via reflection.
     */
    public static JAXBContext createContext( String contextPath,
                                             ClassLoader classLoader, Map<String,Object> properties ) throws JAXBException {
        FinalArrayList<Class> classes = new FinalArrayList<>();
        StringTokenizer tokens = new StringTokenizer(contextPath,":");
        List<Class> indexedClasses;

        // at least on of these must be true per package
        boolean foundObjectFactory;
        boolean foundJaxbIndex;

        while(tokens.hasMoreTokens()) {
            foundObjectFactory = foundJaxbIndex = false;
            String pkg = tokens.nextToken();

            // look for ObjectFactory and load it
            final Class<?> o;
            try {
                o = classLoader.loadClass(pkg+".ObjectFactory");
                classes.add(o);
                foundObjectFactory = true;
            } catch (ClassNotFoundException e) {
                // not necessarily an error
            }

            // look for jaxb.index and load the list of classes
            try {
                indexedClasses = loadIndexedClasses(pkg, classLoader);
            } catch (IOException e) {
                //TODO: think about this more
                throw new JAXBException(e);
            }
            if(indexedClasses != null) {
                classes.addAll(indexedClasses);
                foundJaxbIndex = true;
            }

            if( !(foundObjectFactory || foundJaxbIndex) ) {
                throw new JAXBException( Messages.BROKEN_CONTEXTPATH.format(pkg));
            }
        }


        return createContext(classes.toArray(new Class[0]),properties);
    }

    /**
     * Look for jaxb.index file in the specified package and load it's contents
     *
     * @param pkg package name to search in
     * @param classLoader ClassLoader to search in
     * @return a List of Class objects to load, null if there weren't any
     * @throws IOException if there is an error reading the index file
     * @throws JAXBException if there are any errors in the index file
     */
    private static List<Class> loadIndexedClasses(String pkg, ClassLoader classLoader) throws IOException, JAXBException {
        final String resource = pkg.replace('.', '/') + "/jaxb.index";
        final InputStream resourceAsStream = classLoader.getResourceAsStream(resource);

        if (resourceAsStream == null) {
            return null;
        }

        try (BufferedReader in = new BufferedReader(new InputStreamReader(resourceAsStream, StandardCharsets.UTF_8))) {
            FinalArrayList<Class> classes = new FinalArrayList<>();
            String className = in.readLine();
            while (className != null) {
                className = className.trim();
                if (className.startsWith("#") || (className.length() == 0)) {
                    className = in.readLine();
                    continue;
                }

                if (className.endsWith(".class")) {
                    throw new JAXBException(Messages.ILLEGAL_ENTRY.format(className));
                }

                try {
                    classes.add(classLoader.loadClass(pkg + '.' + className));
                } catch (ClassNotFoundException e) {
                    throw new JAXBException(Messages.ERROR_LOADING_CLASS.format(className, resource), e);
                }

                className = in.readLine();
            }
            return classes;
        }
    }

    public static final String USE_JAXB_PROPERTIES = "_useJAXBProperties";
}
