/*
 * 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 com.sun.tools.xjc.reader.xmlschema;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JJavaName;
import com.sun.codemodel.JPackage;
import com.sun.istack.NotNull;
import com.sun.tools.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.xjc.model.CClassInfo;
import com.sun.tools.xjc.model.CClassInfoParent;
import com.sun.tools.xjc.model.CElement;
import com.sun.tools.xjc.model.CElementInfo;
import com.sun.tools.xjc.model.CTypeInfo;
import com.sun.tools.xjc.model.TypeUse;
import com.sun.tools.xjc.model.CClass;
import com.sun.tools.xjc.model.CNonElement;
import com.sun.tools.xjc.reader.Ring;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BISchemaBinding;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.LocalScoping;
import com.sun.xml.xsom.XSComplexType;
import com.sun.xml.xsom.XSComponent;
import com.sun.xml.xsom.XSDeclaration;
import com.sun.xml.xsom.XSElementDecl;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSchemaSet;
import com.sun.xml.xsom.XSSimpleType;
import com.sun.xml.xsom.XSType;
import com.sun.xml.xsom.impl.util.SchemaWriter;
import com.sun.xml.xsom.util.ComponentNameFunction;

import org.xml.sax.Locator;

import javax.xml.XMLConstants;

/**
 * Manages association between {@link XSComponent}s and generated
 * {@link CTypeInfo}s.
 *
 * <p>
 * This class determines which component is mapped to (or is not mapped to)
 * what types.
 *
 * @author
 *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
 */
public final class ClassSelector extends BindingComponent {
    /** Center of owner classes. */
    private final BGMBuilder builder = Ring.get(BGMBuilder.class);


    /**
     * Map from XSComponents to {@link Binding}s. Keeps track of all
     * content interfaces that are already built or being built.
     */
    private final Map<XSComponent,Binding> bindMap = new HashMap<>();

    /**
     * UGLY HACK.
     * <p>
     * To avoid cyclic dependency between binding elements and types,
     * we need additional markers that tell which elements are definitely not bound
     * to a class.
     * <p>
     * the cyclic dependency is as follows:
     * elements need to bind its types first, because otherwise it can't
     * determine T of {@literal JAXBElement<T>}.
     * OTOH, types need to know whether its parent is bound to a class to decide
     * which class name to use.
     */
    /*package*/ final Map<XSComponent,CElementInfo> boundElements = new HashMap<>();

    /**
     * A list of {@link Binding}s object that needs to be built.
     */
    private final Stack<Binding> bindQueue = new Stack<>();

    /**
     * {@link CClassInfo}s that are already {@link Binding#build() built}.
     */
    private final Set<CClassInfo> built = new HashSet<>();

    /**
     * Object that determines components that are mapped
     * to classes.
     */
    private final ClassBinder classBinder;

    /**
     * {@link CClassInfoParent}s that determines where a new class
     * should be created.
     */
    private final Stack<CClassInfoParent> classScopes = new Stack<>();

    /**
     * The component that is being bound to {@link #currentBean}.
     */
    private XSComponent currentRoot;
    /**
     * The bean representation we are binding right now.
     */
    private CClassInfo currentBean;


    private final class Binding {
        private final XSComponent sc;
        private final CTypeInfo bean;

        public Binding(XSComponent sc, CTypeInfo bean) {
            this.sc = sc;
            this.bean = bean;
        }

        void build() {
            if(!(this.bean instanceof CClassInfo))
                return; // no need to "build"

            CClassInfo bean = (CClassInfo)this.bean;

            if(!built.add(bean))
                return; // already built

            for( String reservedClassName : reservedClassNames ) {
                if( bean.getName().equals(reservedClassName) ) {
                    getErrorReporter().error( sc.getLocator(),
                        Messages.ERR_RESERVED_CLASS_NAME, reservedClassName );
                    break;
                }
            }

            // if this schema component is an element declaration
            // and it satisfies a set of conditions specified in the spec,
            // this class will receive a constructor.
            if(needValueConstructor(sc)) {
                // TODO: fragile. There is no guarantee that the property name
                // is in fact "value".
                bean.addConstructor("value");
            }

            if(bean.javadoc==null)
                addSchemaFragmentJavadoc(bean,sc);

            // build the body
            if(builder.getGlobalBinding().getFlattenClasses()==LocalScoping.NESTED)
                pushClassScope(bean);
            else
                pushClassScope(bean.parent());
            XSComponent oldRoot = currentRoot;
            CClassInfo oldBean = currentBean;
            currentRoot = sc;
            currentBean = bean;
            sc.visit(Ring.get(BindRed.class));
            currentBean = oldBean;
            currentRoot = oldRoot;
            popClassScope();

            // acknowledge property customization on this schema component,
            // since it is OK to have a customization at the point of declaration
            // even when no one is using it.
            BIProperty prop = builder.getBindInfo(sc).get(BIProperty.class);
            if(prop!=null)  prop.markAsAcknowledged();
        }
    }


    // should be instanciated only from BGMBuilder.
    public ClassSelector() {
        classBinder = new Abstractifier(new DefaultClassBinder());
        Ring.add(ClassBinder.class,classBinder);

        classScopes.push(null);  // so that the getClassFactory method returns null

        XSComplexType anyType = Ring.get(XSSchemaSet.class).getComplexType(XMLConstants.W3C_XML_SCHEMA_NS_URI,"anyType");
        bindMap.put(anyType,new Binding(anyType,CBuiltinLeafInfo.ANYTYPE));
    }

    /** Gets the current class scope. */
    public CClassInfoParent getClassScope() {
        assert !classScopes.isEmpty();
        return classScopes.peek();
    }

    public void pushClassScope(CClassInfoParent clsFctry ) {
        assert clsFctry!=null;
        classScopes.push(clsFctry);
    }

    public void popClassScope() {
        classScopes.pop();
    }

    public XSComponent getCurrentRoot() {
        return currentRoot;
    }

    public CClassInfo getCurrentBean() {
        return currentBean;
    }

    /**
     * Checks if the given component is bound to a class.
     */
    public CElement isBound(XSElementDecl x, XSComponent referer ) {
        CElementInfo r = boundElements.get(x);
        if(r!=null)
            return r;
        return bindToType(x,referer);
    }

    /**
     * Checks if the given component is being mapped to a type.
     * If so, build that type and return that object.
     * If it is not being mapped to a type item, return null.
     */
    public CTypeInfo bindToType( XSComponent sc, XSComponent referer ) {
        return _bindToClass(sc,referer,false);
    }

    //
    // some schema components are guaranteed to map to a particular CTypeInfo.
    // the following versions capture those constraints in the signature
    // and making the bindToType invocation more type safe.
    //

    public CElement bindToType( XSElementDecl e, XSComponent referer ) {
        return (CElement)_bindToClass(e,referer,false);
    }

    public CClass bindToType( XSComplexType t, XSComponent referer, boolean cannotBeDelayed ) {
        // this assumption that a complex type always binds to a ClassInfo
        // does not hold for xs:anyType --- our current approach of handling
        // this idiosynchracy is to make sure that xs:anyType doesn't use
        // this codepath.
        return (CClass)_bindToClass(t,referer,cannotBeDelayed);
    }

    public TypeUse bindToType( XSType t, XSComponent referer ) {
        if(t instanceof XSSimpleType) {
            return Ring.get(SimpleTypeBuilder.class).build((XSSimpleType)t);
        } else
            return (CNonElement)_bindToClass(t,referer,false);
    }

    /**
     * The real meat of the "bindToType" code.
     *
     * @param cannotBeDelayed
     *      if the binding of the body of the class cannot be defered
     *      and needs to be done immediately. If the flag is false,
     *      the binding of the body will be done later, to avoid
     *      cyclic binding problem.
     * @param referer
     *      The component that refers to {@code sc}. This can be null,
     *      if figuring out the referer is too hard, in which case
     *      the error message might be less user friendly.
     */
    // TODO: consider getting rid of "cannotBeDelayed"
    CTypeInfo _bindToClass( @NotNull XSComponent sc, XSComponent referer, boolean cannotBeDelayed ) {
        // check if this class is already built.
        if(!bindMap.containsKey(sc)) {
            // craete a bind task

            // if this is a global declaration, make sure they will be generated
            // under a package.
            boolean isGlobal = false;
            if( sc instanceof XSDeclaration ) {
                isGlobal = ((XSDeclaration)sc).isGlobal();
                if( isGlobal )
                    pushClassScope( new CClassInfoParent.Package(
                        getPackage(((XSDeclaration)sc).getTargetNamespace())) );
            }

            // otherwise check if this component should become a class.
            CElement bean = sc.apply(classBinder);

            if( isGlobal )
                popClassScope();

            if(bean==null)
                return null;

            // can this namespace generate a class?
            if (bean instanceof CClassInfo) {
                XSSchema os = sc.getOwnerSchema();
                BISchemaBinding sb = builder.getBindInfo(os).get(BISchemaBinding.class);
                if(sb!=null && !sb.map) {
                    // nope
                    getErrorReporter().error(sc.getLocator(),
                        Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS, sc.apply( new ComponentNameFunction() ) );
                    getErrorReporter().error(sb.getLocation(),
                        Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS_MAP_FALSE, os.getTargetNamespace() );
                    if(referer!=null)
                        getErrorReporter().error(referer.getLocator(),
                            Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS_REFERER, referer.apply( new ComponentNameFunction() ) );
                }
            }


            queueBuild( sc, bean );
        }

        Binding bind = bindMap.get(sc);
        if( cannotBeDelayed )
            bind.build();

        return bind.bean;
    }

    /**
     * Runs all the pending build tasks.
     */
    public void executeTasks() {
        while( bindQueue.size()!=0 )
            bindQueue.pop().build();
    }








    /**
     * Determines if the given component needs to have a value
     * constructor (a constructor that takes a parmater.) on ObjectFactory.
     */
    private boolean needValueConstructor( XSComponent sc ) {
        if(!(sc instanceof XSElementDecl))  return false;

        XSElementDecl decl = (XSElementDecl)sc;
        return decl.getType().isSimpleType();
    }

    private static final String[] reservedClassNames = new String[]{"ObjectFactory"};

    public void queueBuild( XSComponent sc, CElement bean ) {
        // it is an error if the same component is built twice,
        // or the association is modified.
        Binding b = new Binding(sc,bean);
        bindQueue.push(b);
        Binding old = bindMap.put(sc, b);
        assert old==null || old.bean==bean;
    }


    /**
     * Copies a schema fragment into the javadoc of the generated class.
     */
    private void addSchemaFragmentJavadoc( CClassInfo bean, XSComponent sc ) {

        // first, pick it up from <documentation> if any.
        String doc = builder.getBindInfo(sc).getDocumentation();
        if(doc!=null)
            append(bean, doc);

        // then the description of where this component came from
        Locator loc = sc.getLocator();
        String fileName = null;
        if(loc!=null) {
            fileName = loc.getPublicId();
            if(fileName==null)
                fileName = loc.getSystemId();
        }
        if(fileName==null)  fileName="";

        String lineNumber=Messages.format( Messages.JAVADOC_LINE_UNKNOWN);
        if(loc!=null && loc.getLineNumber()!=-1)
            lineNumber = String.valueOf(loc.getLineNumber());

        String componentName = sc.apply( new ComponentNameFunction() );
        String jdoc = Messages.format( Messages.JAVADOC_HEADING, componentName, fileName, lineNumber );
        append(bean,jdoc);

        // then schema fragment
        StringWriter out = new StringWriter();
        out.write("<pre>{@code\n");
        SchemaWriter sw = new SchemaWriter(out);
        sc.visit(sw);
        out.write("}</pre>");
        append(bean,out.toString());
    }

    private void append(CClassInfo bean, String doc) {
        if(bean.javadoc==null)
            bean.javadoc = doc+'\n';
        else
            bean.javadoc += '\n'+doc+'\n';
    }


    /**
     * Set of package names that are tested (set of {@code String}s.)
     *
     * This set is used to avoid duplicating "incorrect package name"
     * errors.
     */
    private static Set<String> checkedPackageNames = new HashSet<>();

    /**
     * Gets the Java package to which classes from
     * this namespace should go.
     *
     * <p>
     * Usually, the getOuterClass method should be used
     * to determine where to put a class.
     */
    public JPackage getPackage(String targetNamespace) {
        XSSchema s = Ring.get(XSSchemaSet.class).getSchema(targetNamespace);

        BISchemaBinding sb =
            builder.getBindInfo(s).get(BISchemaBinding.class);
        if(sb!=null)    sb.markAsAcknowledged();

        String name = null;

        // "-p" takes precedence over everything else
        if( builder.defaultPackage1 != null )
            name = builder.defaultPackage1;

        // use the <jaxb:package> customization
        if( name == null && sb!=null && sb.getPackageName()!=null )
            name = sb.getPackageName();

        // the JAX-RPC option goes below the <jaxb:package>
        if( name == null && builder.defaultPackage2 != null )
            name = builder.defaultPackage2;

        // generate the package name from the targetNamespace
        if( name == null )
            name = builder.getNameConverter().toPackageName( targetNamespace );

        // hardcode a package name because the code doesn't compile
        // if it generated into the default java package
        if( name == null )
            name = "generated"; // the last resort


        // check if the package name is a valid name.
        if( checkedPackageNames.add(name) ) {
            // this is the first time we hear about this package name.
            if( !JJavaName.isJavaPackageName(name) )
                // TODO: s.getLocator() is not very helpful.
                // ideally, we'd like to use the locator where this package name
                // comes from.
                getErrorReporter().error(s.getLocator(),
                    Messages.ERR_INCORRECT_PACKAGE_NAME, targetNamespace, name );
        }

        return Ring.get(JCodeModel.class)._package(name);
    }
}
