/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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.directory.server.core.schema;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.NamingException;

import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.server.core.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
import org.apache.directory.server.core.interceptor.context.ListOperationContext;
import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
import org.apache.directory.server.core.partition.Partition;
import org.apache.directory.shared.ldap.constants.MetaSchemaConstants;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.SchemaManager;
import org.apache.directory.shared.ldap.schema.parsers.LdapComparatorDescription;
import org.apache.directory.shared.ldap.schema.parsers.NormalizerDescription;
import org.apache.directory.shared.ldap.schema.parsers.SyntaxCheckerDescription;
import org.apache.directory.shared.ldap.schema.registries.AbstractSchemaLoader;
import org.apache.directory.shared.ldap.schema.registries.Registries;
import org.apache.directory.shared.ldap.schema.registries.Schema;
import org.apache.directory.shared.ldap.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * A class that loads schemas from a partition.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$
 */
public class PartitionSchemaLoader extends AbstractSchemaLoader
{
    /** static class logger */
    private static final Logger LOG = LoggerFactory.getLogger( PartitionSchemaLoader.class );

    private final SchemaPartitionDao dao;
    private Partition partition;

    /** The attributeType registry */
    private SchemaManager schemaManager;

    private final AttributeType mOidAT;
    private final AttributeType mNameAT;
    private final AttributeType cnAT;
    private final AttributeType byteCodeAT;
    private final AttributeType descAT;
    private final AttributeType fqcnAT;

    private static Map<String, LdapDN> staticAttributeTypeDNs = new HashMap<String, LdapDN>();
    private static Map<String, LdapDN> staticMatchingRulesDNs = new HashMap<String, LdapDN>();
    private static Map<String, LdapDN> staticObjectClassesDNs = new HashMap<String, LdapDN>();
    private static Map<String, LdapDN> staticComparatorsDNs = new HashMap<String, LdapDN>();
    private static Map<String, LdapDN> staticNormalizersDNs = new HashMap<String, LdapDN>();
    private static Map<String, LdapDN> staticSyntaxCheckersDNs = new HashMap<String, LdapDN>();
    private static Map<String, LdapDN> staticSyntaxesDNs = new HashMap<String, LdapDN>();


    public PartitionSchemaLoader( Partition partition, SchemaManager schemaManager ) throws Exception
    {
        this.partition = partition;
        this.schemaManager = schemaManager;

        dao = new SchemaPartitionDaoImpl( this.partition, schemaManager );
        mOidAT = schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_OID_AT );
        mNameAT = schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_NAME_AT );
        cnAT = schemaManager.lookupAttributeTypeRegistry( SchemaConstants.CN_AT );
        byteCodeAT = schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_BYTECODE_AT );
        descAT = schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_DESCRIPTION_AT );
        fqcnAT = schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_FQCN_AT );

        initStaticDNs( "system" );
        initStaticDNs( "core" );
        initStaticDNs( "apache" );
        initStaticDNs( "apachemeta" );
        initStaticDNs( MetaSchemaConstants.SCHEMA_OTHER );
        initStaticDNs( "collective" );
        initStaticDNs( "java" );
        initStaticDNs( "cosine" );
        initStaticDNs( "inetorgperson" );
    }


    private void initStaticDNs( String schemaName ) throws Exception
    {

        // Initialize AttributeType Dns
        LdapDN dn = new LdapDN( SchemaConstants.ATTRIBUTES_TYPE_PATH, "cn=" + schemaName, SchemaConstants.OU_SCHEMA );

        dn.normalize( schemaManager.getNormalizerMapping() );
        staticAttributeTypeDNs.put( schemaName, dn );

        // Initialize ObjectClasses Dns
        dn = new LdapDN( SchemaConstants.OBJECT_CLASSES_PATH, "cn=" + schemaName, SchemaConstants.OU_SCHEMA );

        dn.normalize( schemaManager.getNormalizerMapping() );
        staticObjectClassesDNs.put( schemaName, dn );

        // Initialize MatchingRules Dns
        dn = new LdapDN( SchemaConstants.MATCHING_RULES_PATH, "cn=" + schemaName, SchemaConstants.OU_SCHEMA );

        dn.normalize( schemaManager.getNormalizerMapping() );
        staticMatchingRulesDNs.put( schemaName, dn );

        // Initialize Comparators Dns
        dn = new LdapDN( SchemaConstants.COMPARATORS_PATH, "cn=" + schemaName, SchemaConstants.OU_SCHEMA );

        dn.normalize( schemaManager.getNormalizerMapping() );
        staticComparatorsDNs.put( schemaName, dn );

        // Initialize Normalizers Dns
        dn = new LdapDN( SchemaConstants.NORMALIZERS_PATH, "cn=" + schemaName, SchemaConstants.OU_SCHEMA );

        dn.normalize( schemaManager.getNormalizerMapping() );
        staticNormalizersDNs.put( schemaName, dn );

        // Initialize SyntaxCheckers Dns
        dn = new LdapDN( SchemaConstants.SYNTAX_CHECKERS_PATH, "cn=" + schemaName, SchemaConstants.OU_SCHEMA );

        dn.normalize( schemaManager.getNormalizerMapping() );
        staticSyntaxCheckersDNs.put( schemaName, dn );

        // Initialize Syntaxes Dns
        dn = new LdapDN( SchemaConstants.SYNTAXES_PATH, "cn=" + schemaName, SchemaConstants.OU_SCHEMA );

        dn.normalize( schemaManager.getNormalizerMapping() );
        staticSyntaxesDNs.put( schemaName, dn );

    }


    /**
     * Helper class used to update the static DNs for each kind of Schema Object
     */
    private LdapDN updateDNs( Map<String, LdapDN> staticDNs, String path, Schema schema ) throws NamingException
    {
        LdapDN dn = staticDNs.get( schema.getSchemaName() );

        if ( dn == null )
        {
            dn = new LdapDN( path, "cn=" + schema.getSchemaName(), SchemaConstants.OU_SCHEMA );

            dn.normalize( schemaManager.getNormalizerMapping() );
            staticDNs.put( schema.getSchemaName(), dn );
        }

        return dn;
    }


    /**
     * Lists the names of the schemas that depend on the schema name provided.
     * 
     * @param schemaName the name of the schema to find dependents for
     * @return a set of schemas (String names) that depend on the schema
     * @throws NamingException if there are problems searching the schema partition
     */
    public Set<String> listDependentSchemaNames( String schemaName ) throws Exception
    {
        Set<String> dependees = new HashSet<String>();
        Set<ServerEntry> results = dao.listSchemaDependents( schemaName );

        if ( results.isEmpty() )
        {
            return dependees;
        }

        for ( ServerEntry sr : results )
        {
            EntryAttribute cn = sr.get( cnAT );
            dependees.add( cn.getString() );
        }

        return dependees;
    }


    /**
     * Lists the names of the enabled schemas that depend on the schema name 
     * provided.
     * 
     * @param schemaName the name of the schema to find dependents for
     * @return a set of enabled schemas (String names) that depend on the schema
     * @throws NamingException if there are problems searching the schema partition
     */
    public Set<String> listEnabledDependentSchemaNames( String schemaName ) throws Exception
    {
        Set<String> dependees = new HashSet<String>();
        Set<ServerEntry> results = dao.listEnabledSchemaDependents( schemaName );

        if ( results.isEmpty() )
        {
            return dependees;
        }

        for ( ServerEntry sr : results )
        {
            EntryAttribute cn = sr.get( cnAT );
            dependees.add( cn.getString() );
        }

        return dependees;
    }


    public Map<String, Schema> getSchemas() throws Exception
    {
        return dao.getSchemas();
    }


    public Set<String> getSchemaNames() throws Exception
    {
        return dao.getSchemaNames();
    }


    public Schema getSchema( String schemaName )
    {
        try
        {
            return dao.getSchema( schemaName );
        }
        catch ( Exception e )
        {
            // TODO fixme
            return null;
        }
    }


    /**
     * {@inheritDoc}
     */
    public final void load( Schema schema, Registries targetRegistries, boolean isDepLoad ) throws Exception
    {
        // if we're loading a dependency and it has not been enabled on 
        // disk then enable it on disk before we proceed to load it
        if ( schema.isDisabled() && isDepLoad )
        {
            dao.enableSchema( schema.getSchemaName() );
        }

        if ( targetRegistries.isSchemaLoaded( schema.getSchemaName() ) )
        {
            LOG.debug( "schema {} already seems to be loaded", schema.getSchemaName() );
            return;
        }

        LOG.debug( "loading {} schema ...", schema.getSchemaName() );

        loadComparators( schema );
        loadNormalizers( schema );
        loadSyntaxCheckers( schema );
        loadSyntaxes( schema );
        loadMatchingRules( schema );
        loadAttributeTypes( schema );
        loadObjectClasses( schema );
        loadMatchingRuleUses( schema );
        loadDitContentRules( schema );
        loadNameForms( schema );

        // order does matter here so some special trickery is needed
        // we cannot load a DSR before the DSRs it depends on are loaded?
        // TODO need to confirm this ( or we must make the class for this and use deferred 
        // resolution until everything is available?

        loadDitStructureRules( schema );

        notifyListenerOrRegistries( schema, targetRegistries );
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadAttributeTypes( Schema... schemas ) throws Exception
    {
        List<Entry> attributeTypeList = new ArrayList<Entry>();

        for ( Schema schema : schemas )
        {
            LdapDN dn = updateDNs( staticAttributeTypeDNs, SchemaConstants.ATTRIBUTES_TYPE_PATH, schema );

            // Check that we don't have an entry in the Dit for this schema
            if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
            {
                // No : get out, no AttributeType to load
                return attributeTypeList;
            }

            LOG.debug( "{} schema: loading attributeTypes", schema.getSchemaName() );

            EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );

            // Loop on all the AttributeTypes and add them to the list
            while ( list.next() )
            {
                ServerEntry result = list.get();

                attributeTypeList.add( result );
            }
        }

        return attributeTypeList;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadComparators( Schema... schemas ) throws Exception
    {
        List<Entry> comparatorList = new ArrayList<Entry>();

        if ( schemas == null )
        {
            return comparatorList;
        }

        for ( Schema schema : schemas )
        {
            LdapDN dn = updateDNs( staticComparatorsDNs, SchemaConstants.COMPARATORS_PATH, schema );

            if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
            {
                return comparatorList;
            }

            LOG.debug( "{} schema: loading comparators", schema.getSchemaName() );

            EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );

            while ( list.next() )
            {
                ClonedServerEntry entry = list.get();

                comparatorList.add( entry );
            }
        }

        return comparatorList;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadDitContentRules( Schema... schemas ) throws Exception
    {
        LOG.error( "DitContentRule loading NYI" );

        return null;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadDitStructureRules( Schema... schemas ) throws Exception
    {
        LOG.error( "DitStructureRule loading NYI" );

        return null;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadMatchingRules( Schema... schemas ) throws Exception
    {
        List<Entry> matchingRuleList = new ArrayList<Entry>();

        if ( schemas == null )
        {
            return matchingRuleList;
        }

        for ( Schema schema : schemas )
        {
            LdapDN dn = updateDNs( staticMatchingRulesDNs, SchemaConstants.MATCHING_RULES_PATH, schema );

            if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
            {
                return matchingRuleList;
            }

            LOG.debug( "{} schema: loading matchingRules", schema.getSchemaName() );

            EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );

            while ( list.next() )
            {
                ServerEntry entry = list.get();

                matchingRuleList.add( entry );
            }
        }

        return matchingRuleList;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws Exception
    {
        LOG.error( "MatchingRuleUse loading NYI" );

        return null;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadNameForms( Schema... schemas ) throws Exception
    {
        LOG.error( "NameForm loading NYI" );

        return null;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadNormalizers( Schema... schemas ) throws Exception
    {
        List<Entry> normalizerList = new ArrayList<Entry>();

        if ( schemas == null )
        {
            return normalizerList;
        }

        for ( Schema schema : schemas )
        {
            LdapDN dn = updateDNs( staticNormalizersDNs, SchemaConstants.NORMALIZERS_PATH, schema );

            if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
            {
                return normalizerList;
            }

            LOG.debug( "{} schema: loading normalizers", schema.getSchemaName() );

            EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );

            while ( list.next() )
            {
                ClonedServerEntry entry = list.get();

                normalizerList.add( entry );
            }
        }

        return normalizerList;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadObjectClasses( Schema... schemas ) throws Exception
    {
        List<Entry> objectClassList = new ArrayList<Entry>();

        if ( schemas == null )
        {
            return objectClassList;
        }

        for ( Schema schema : schemas )
        {
            LdapDN dn = updateDNs( staticObjectClassesDNs, SchemaConstants.OBJECT_CLASSES_PATH, schema );

            if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
            {
                return objectClassList;
            }

            LOG.debug( "{} schema: loading objectClasses", schema.getSchemaName() );

            EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );

            while ( list.next() )
            {
                ClonedServerEntry entry = list.get();

                objectClassList.add( entry );
            }
        }

        return objectClassList;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadSyntaxes( Schema... schemas ) throws Exception
    {
        List<Entry> syntaxList = new ArrayList<Entry>();

        if ( schemas == null )
        {
            return syntaxList;
        }

        for ( Schema schema : schemas )
        {
            LdapDN dn = updateDNs( staticSyntaxesDNs, SchemaConstants.SYNTAXES_PATH, schema );

            if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
            {
                return syntaxList;
            }

            LOG.debug( "{} schema: loading syntaxes", schema.getSchemaName() );

            EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );

            while ( list.next() )
            {
                ServerEntry entry = list.get();

                syntaxList.add( entry );
            }
        }

        return syntaxList;
    }


    /**
     * {@inheritDoc}
     */
    public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws Exception
    {
        List<Entry> syntaxCheckerList = new ArrayList<Entry>();

        if ( schemas == null )
        {
            return syntaxCheckerList;
        }

        for ( Schema schema : schemas )
        {
            LdapDN dn = updateDNs( staticSyntaxCheckersDNs, SchemaConstants.SYNTAX_CHECKERS_PATH, schema );

            if ( !partition.hasEntry( new EntryOperationContext( null, dn ) ) )
            {
                return syntaxCheckerList;
            }

            LOG.debug( "{} schema: loading syntaxCsheckers", schema.getSchemaName() );

            EntryFilteringCursor list = partition.list( new ListOperationContext( null, dn ) );

            while ( list.next() )
            {
                ServerEntry entry = list.get();

                syntaxCheckerList.add( entry );
            }
        }

        return syntaxCheckerList;
    }


    private String getOid( ServerEntry entry ) throws Exception
    {
        EntryAttribute oid = entry.get( mOidAT );

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

        return oid.getString();
    }


    private NormalizerDescription getNormalizerDescription( String schemaName, ServerEntry entry ) throws Exception
    {
        NormalizerDescription description = new NormalizerDescription( getOid( entry ) );
        List<String> values = new ArrayList<String>();
        values.add( schemaName );
        description.addExtension( MetaSchemaConstants.X_SCHEMA, values );
        description.setFqcn( entry.get( fqcnAT ).getString() );

        EntryAttribute desc = entry.get( descAT );
        if ( desc != null && desc.size() > 0 )
        {
            description.setDescription( desc.getString() );
        }

        EntryAttribute bytecode = entry.get( byteCodeAT );

        if ( bytecode != null && bytecode.size() > 0 )
        {
            byte[] bytes = bytecode.getBytes();
            description.setBytecode( new String( Base64.encode( bytes ) ) );
        }

        return description;
    }


    private ClonedServerEntry lookupPartition( LdapDN dn ) throws Exception
    {
        return partition.lookup( new LookupOperationContext( null, dn ) );
    }


    private LdapComparatorDescription getLdapComparatorDescription( String schemaName, ServerEntry entry )
        throws Exception
    {
        LdapComparatorDescription description = new LdapComparatorDescription( getOid( entry ) );
        List<String> values = new ArrayList<String>();
        values.add( schemaName );
        description.addExtension( MetaSchemaConstants.X_SCHEMA, values );
        description.setFqcn( entry.get( fqcnAT ).getString() );

        EntryAttribute desc = entry.get( descAT );

        if ( desc != null && desc.size() > 0 )
        {
            description.setDescription( desc.getString() );
        }

        EntryAttribute bytecode = entry.get( byteCodeAT );

        if ( bytecode != null && bytecode.size() > 0 )
        {
            byte[] bytes = bytecode.getBytes();
            description.setBytecode( new String( Base64.encode( bytes ) ) );
        }

        return description;
    }


    private SyntaxCheckerDescription getSyntaxCheckerDescription( String schemaName, ServerEntry entry )
        throws Exception
    {
        SyntaxCheckerDescription description = new SyntaxCheckerDescription( getOid( entry ) );
        List<String> values = new ArrayList<String>();
        values.add( schemaName );
        description.addExtension( MetaSchemaConstants.X_SCHEMA, values );
        description.setFqcn( entry.get( fqcnAT ).getString() );

        EntryAttribute desc = entry.get( descAT );

        if ( desc != null && desc.size() > 0 )
        {
            description.setDescription( desc.getString() );
        }

        EntryAttribute bytecode = entry.get( byteCodeAT );

        if ( bytecode != null && bytecode.size() > 0 )
        {
            byte[] bytes = bytecode.getBytes();
            description.setBytecode( new String( Base64.encode( bytes ) ) );
        }

        return description;
    }


    /**
     * @return the dao
     */
    public SchemaPartitionDao getDao()
    {
        return dao;
    }
}
