/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.xmlbeans.impl.schema;

import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.SchemaParticle;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlErrorCodes;
import org.apache.xmlbeans.impl.xb.xsdschema.Attribute;
import org.apache.xmlbeans.impl.xb.xsdschema.Element;
import org.apache.xmlbeans.impl.xb.xsdschema.KeyrefDocument.Keyref;
import org.apache.xmlbeans.impl.xb.xsdschema.TopLevelElement;

import javax.xml.namespace.QName;
import java.math.BigInteger;
import java.util.*;

public class StscResolver {
    /**
     * Does a topo walk of all the types to resolve them.
     */
    public static void resolveAll() {
        // resolve tree of types
        StscState state = StscState.get();

        SchemaType[] documentTypes = state.documentTypes();
        for (int i = 0; i < documentTypes.length; i++) {
            resolveSubstitutionGroup((SchemaTypeImpl) documentTypes[i]);
        }

        List<SchemaType> allSeenTypes = new ArrayList<>();
        allSeenTypes.addAll(Arrays.asList(state.documentTypes()));
        allSeenTypes.addAll(Arrays.asList(state.attributeTypes()));
        allSeenTypes.addAll(Arrays.asList(state.redefinedGlobalTypes()));
        allSeenTypes.addAll(Arrays.asList(state.globalTypes()));

        for (int i = 0; i < allSeenTypes.size(); i++) {
            SchemaType gType = allSeenTypes.get(i);
            resolveType((SchemaTypeImpl) gType);
            allSeenTypes.addAll(Arrays.asList(gType.getAnonymousTypes()));
        }

        // Resolve all keyref refs
        resolveIdentityConstraints();
    }

    public static boolean resolveType(SchemaTypeImpl sImpl) {
        if (sImpl.isResolved()) {
            return true;
        }
        if (sImpl.isResolving()) {
            StscState.get().error("Cyclic dependency error", XmlErrorCodes.CYCLIC_DEPENDENCY, sImpl.getParseObject());
            return false; // cyclic dependency error
        }
        // System.out.println("Resolving " + sImpl);

        sImpl.startResolving();

        if (sImpl.isDocumentType()) {
            resolveDocumentType(sImpl);
        } else if (sImpl.isAttributeType()) {
            resolveAttributeType(sImpl);
        } else if (sImpl.isSimpleType()) {
            StscSimpleTypeResolver.resolveSimpleType(sImpl);
        } else {
            StscComplexTypeResolver.resolveComplexType(sImpl);
        }

        sImpl.finishResolving();
        // System.out.println("Finished resolving " + sImpl);
        return true;
    }

    public static boolean resolveSubstitutionGroup(SchemaTypeImpl sImpl) {
        assert sImpl.isDocumentType();

        if (sImpl.isSGResolved()) {
            return true;
        }
        if (sImpl.isSGResolving()) {
            StscState.get().error("Cyclic dependency error", XmlErrorCodes.CYCLIC_DEPENDENCY, sImpl.getParseObject());
            return false; // cyclic dependency error
        }

        sImpl.startResolvingSGs();

        // Resolve substitution group

        TopLevelElement elt = (TopLevelElement) sImpl.getParseObject();
        SchemaTypeImpl substitutionGroup = null;
        QName eltName = new QName(sImpl.getTargetNamespace(), elt.getName());

        // BUG: How do I tell if the type is in this compilation unit?
        if (elt.isSetSubstitutionGroup()) {
            substitutionGroup = StscState.get().findDocumentType(elt.getSubstitutionGroup(),
                sImpl.getChameleonNamespace(), sImpl.getTargetNamespace());

            if (substitutionGroup == null) {
                StscState.get().notFoundError(elt.getSubstitutionGroup(), SchemaType.ELEMENT, elt.xgetSubstitutionGroup(), true);
            }
            // recovery - ignore substitution group
            else if (!resolveSubstitutionGroup(substitutionGroup)) {
                substitutionGroup = null;
            } else {
                sImpl.setSubstitutionGroup(elt.getSubstitutionGroup());
            }
        }

        // Walk up the chain of subtitution groups adding this schematype to each head's
        // member list
        while (substitutionGroup != null) {

            substitutionGroup.addSubstitutionGroupMember(eltName);

            if (substitutionGroup.getSubstitutionGroup() == null) {
                break;
            }

            substitutionGroup = StscState.get().findDocumentType(
                substitutionGroup.getSubstitutionGroup(), substitutionGroup.getChameleonNamespace(), null/*no dependency added*/);

            assert substitutionGroup != null : "Could not find document type for substitutionGroup";

            if (!resolveSubstitutionGroup(substitutionGroup)) {
                substitutionGroup = null; // cyclic dependency - no subst group
            }

        }

        sImpl.finishResolvingSGs();
        return true;

    }

    public static void resolveDocumentType(SchemaTypeImpl sImpl) {
        assert sImpl.isResolving();

        assert sImpl.isDocumentType();


        // translate the global element associated with this document type
        // and construct a content model which allows just that element

        List<SchemaType> anonTypes = new ArrayList<>();

        SchemaGlobalElementImpl element =
            (SchemaGlobalElementImpl)
                StscTranslator.translateElement(
                    (Element) sImpl.getParseObject(),
                    sImpl.getTargetNamespace(), sImpl.isChameleon(), null, null,
                    anonTypes, sImpl);

        SchemaLocalElementImpl contentModel = null;

        if (element != null) {
            StscState.get().addGlobalElement(element);

            contentModel = new SchemaLocalElementImpl();

            contentModel.setParticleType(SchemaParticle.ELEMENT);
            StscTranslator.copyGlobalElementToLocalElement(element, contentModel);
            contentModel.setMinOccurs(BigInteger.ONE);
            contentModel.setMaxOccurs(BigInteger.ONE);

            contentModel.setTransitionNotes(QNameSet.EMPTY, true);
        }

        Map elementPropertyModel =
            StscComplexTypeResolver.buildContentPropertyModelByQName(
                contentModel, sImpl);

        SchemaTypeImpl baseType = sImpl.getSubstitutionGroup() == null ?
            BuiltinSchemaTypeSystem.ST_ANY_TYPE :
            StscState.get().findDocumentType(sImpl.getSubstitutionGroup(),
                sImpl.isChameleon() ? sImpl.getTargetNamespace() : null, null/*already added*/);

        sImpl.setBaseTypeRef(baseType.getRef());
        sImpl.setBaseDepth(baseType.getBaseDepth() + 1);
        sImpl.setDerivationType(SchemaType.DT_RESTRICTION);
        sImpl.setComplexTypeVariety(SchemaType.ELEMENT_CONTENT);

        sImpl.setContentModel(
            contentModel, new SchemaAttributeModelImpl(),
            elementPropertyModel, Collections.EMPTY_MAP, false);

        sImpl.setWildcardSummary(
            QNameSet.EMPTY, false, QNameSet.EMPTY, false);

        sImpl.setAnonymousTypeRefs(makeRefArray(anonTypes));


    }

    public static void resolveAttributeType(SchemaTypeImpl sImpl) {
        assert sImpl.isResolving();

        assert sImpl.isAttributeType();

        List<SchemaType> anonTypes = new ArrayList<>();

        SchemaGlobalAttributeImpl attribute =
            (SchemaGlobalAttributeImpl) StscTranslator.translateAttribute(
                (Attribute) sImpl.getParseObject(), sImpl.getTargetNamespace(), null,
                sImpl.isChameleon(), anonTypes, sImpl, null, false);

        SchemaAttributeModelImpl attributeModel = new SchemaAttributeModelImpl();

        if (attribute != null) {
            StscState.get().addGlobalAttribute(attribute);

            SchemaLocalAttributeImpl attributeCopy = new SchemaLocalAttributeImpl();
            StscTranslator.copyGlobalAttributeToLocalAttribute(attribute, attributeCopy);
            attributeModel.addAttribute(attributeCopy);
        }

        sImpl.setBaseTypeRef(BuiltinSchemaTypeSystem.ST_ANY_TYPE.getRef());
        sImpl.setBaseDepth(sImpl.getBaseDepth() + 1);
        sImpl.setDerivationType(SchemaType.DT_RESTRICTION);
        sImpl.setComplexTypeVariety(SchemaType.EMPTY_CONTENT);

        Map attributePropertyModel =
            StscComplexTypeResolver.buildAttributePropertyModelByQName(
                attributeModel, sImpl);

        sImpl.setContentModel(
            null, attributeModel, Collections.EMPTY_MAP, attributePropertyModel, false);

        sImpl.setWildcardSummary(
            QNameSet.EMPTY, false, QNameSet.EMPTY, false);

        sImpl.setAnonymousTypeRefs(makeRefArray(anonTypes));
    }

    private static SchemaType.Ref[] makeRefArray(Collection<SchemaType> typeList) {
        return typeList.stream().map(SchemaType::getRef).toArray(SchemaType.Ref[]::new);
    }


    public static void resolveIdentityConstraints() {
        StscState state = StscState.get();
        SchemaIdentityConstraintImpl[] idcs = state.idConstraints();

        for (SchemaIdentityConstraintImpl idc : idcs) {
            if (!idc.isResolved()) {
                Keyref xsdkr = (Keyref) idc.getParseObject();
                QName keyName = xsdkr.getRefer();
                SchemaIdentityConstraintImpl key = null;

                key = state.findIdConstraint(keyName, idc.getChameleonNamespace(), idc.getTargetNamespace());
                if (key == null) {
                    state.notFoundError(keyName, SchemaType.IDENTITY_CONSTRAINT, xsdkr, true);
                } else {
                    if (key.getConstraintCategory() == SchemaIdentityConstraintImpl.CC_KEYREF) {
                        state.error(XmlErrorCodes.IDENTITY_CONSTRAINT_PROPERTIES$KEYREF_REFERS_TO_KEYREF,
                            null, idc.getParseObject());
                    }

                    if (key.getFields().length != idc.getFields().length) {
                        state.error(XmlErrorCodes.IDENTITY_CONSTRAINT_PROPERTIES$KEY_KEYREF_FIELD_COUNT_EQ,
                            null, idc.getParseObject());
                    }

                    idc.setReferencedKey(key.getRef());
                }
            }
        }
    }

}
