/*
 * 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.integ;


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.naming.NamingException;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.LdapName;

import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.DefaultModification;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.ldif.ChangeType;
import org.apache.directory.api.ldap.model.ldif.LdifEntry;
import org.apache.directory.api.ldap.model.ldif.LdifReader;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.name.Rdn;
import org.apache.directory.api.ldap.model.schema.registries.Schema;
import org.apache.directory.api.util.FileUtils;
import org.apache.directory.api.util.Network;
import org.apache.directory.api.util.Strings;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.api.CoreSession;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.LdapCoreSessionConnection;
import org.apache.directory.server.core.api.LdapPrincipal;
import org.apache.directory.server.core.jndi.ServerLdapContext;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.server.ldap.LdapServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Integration test utility methods.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class IntegrationUtils
{
    /** The class logger */
    private static final Logger LOG = LoggerFactory.getLogger( IntegrationUtils.class );

    private static final List<LdapConnection> OPEN_CONNECTIONS = new ArrayList<>();


    /**
     * Deletes the working directory.
     *
     * @param wkdir the working directory to delete
     * @throws IOException if the working directory cannot be deleted
     */
    public static void doDelete( File wkdir ) throws IOException
    {
        if ( wkdir.exists() )
        {
            try
            {
                FileUtils.deleteDirectory( wkdir );
            }
            catch ( IOException e )
            {
                LOG.error( I18n.err( I18n.ERR_115 ), e );
            }
        }
        if ( wkdir.exists() )
        {
            throw new IOException( I18n.err( I18n.ERR_116, wkdir ) );
        }
    }


    /**
     * Inject an ldif String into the server. Dn must be relative to the
     * root.
     *
     * @param service the directory service to use
     * @param ldif the ldif containing entries to add to the server.
     * @throws NamingException if there is a problem adding the entries from the LDIF
     */
    public static void injectEntries( DirectoryService service, String ldif ) throws Exception
    {
        try ( LdifReader reader = new LdifReader() )
        {
            List<LdifEntry> entries = reader.parseLdif( ldif );
    
            for ( LdifEntry entry : entries )
            {
                if ( entry.isEntry() )
                {
                    service.getAdminSession().add(
                        new DefaultEntry( service.getSchemaManager(), entry.getEntry() ) );
                }
                else if ( entry.isChangeModify() )
                {
                    service.getAdminSession().modify(
                        entry.getDn(), entry.getModifications() );
                }
                else
                {
                    String message = I18n.err( I18n.ERR_117, entry.getChangeType() );
                    LOG.error( message );
                    throw new NamingException( message );
                }
            }
        }
    }


    public static LdifEntry getUserAddLdif() throws LdapException
    {
        return getUserAddLdif( "uid=akarasulu,ou=users,ou=system", Strings.getBytesUtf8( "test" ),
            "Alex Karasulu", "Karasulu" );
    }


    public static LdapContext getContext( String principalDn, DirectoryService service, String dn )
        throws Exception
    {
        if ( principalDn == null )
        {
            principalDn = "";
        }

        Dn userDn = new Dn( service.getSchemaManager(), principalDn );
        LdapPrincipal principal = new LdapPrincipal( service.getSchemaManager(), userDn, AuthenticationLevel.SIMPLE );

        if ( dn == null )
        {
            dn = "";
        }

        CoreSession session = service.getSession( principal );

        return new ServerLdapContext( service, session, new LdapName( dn ) );
    }


    public static CoreSession getCoreSession( String principalDn, DirectoryService service, String dn )
        throws LdapException
    {
        if ( principalDn == null )
        {
            principalDn = "";
        }

        Dn userDn = new Dn( service.getSchemaManager(), principalDn );
        LdapPrincipal principal = new LdapPrincipal( service.getSchemaManager(), userDn, AuthenticationLevel.SIMPLE );

        return service.getSession( principal );
    }


    public static LdapContext getSystemContext( DirectoryService service ) throws Exception
    {
        return getContext( ServerDNConstants.ADMIN_SYSTEM_DN, service, ServerDNConstants.SYSTEM_DN );
    }


    public static LdapContext getSchemaContext( DirectoryService service ) throws Exception
    {
        return getContext( ServerDNConstants.ADMIN_SYSTEM_DN, service, SchemaConstants.OU_SCHEMA );
    }


    public static LdapContext getRootContext( DirectoryService service ) throws Exception
    {
        return getContext( ServerDNConstants.ADMIN_SYSTEM_DN, service, "" );
    }


    public static void apply( DirectoryService service, LdifEntry entry ) throws LdapException
    {
        Dn dn = entry.getDn();
        CoreSession session = service.getAdminSession();

        switch ( entry.getChangeType().getChangeType() )
        {
            case ( ChangeType.ADD_ORDINAL ):
                session.add(
                    new DefaultEntry( service.getSchemaManager(), entry.getEntry() ) );
                break;

            case ( ChangeType.DELETE_ORDINAL ):
                session.delete( dn );
                break;

            case ( ChangeType.MODDN_ORDINAL ):
            case ( ChangeType.MODRDN_ORDINAL ):
                Rdn newRdn = new Rdn( entry.getNewRdn() );

                if ( entry.getNewSuperior() != null )
                {
                    // It's a move. The superior have changed
                    // Let's see if it's a rename too
                    Rdn oldRdn = dn.getRdn();
                    Dn newSuperior = new Dn( entry.getNewSuperior() );

                    if ( dn.size() == 0 )
                    {
                        throw new IllegalStateException( I18n.err( I18n.ERR_475 ) );
                    }
                    else if ( oldRdn.equals( newRdn ) )
                    {
                        // Same rdn : it's a move
                        session.move( dn, newSuperior );
                    }
                    else
                    {
                        // it's a move and rename
                        session.moveAndRename( dn, newSuperior, newRdn, entry.isDeleteOldRdn() );
                    }
                }
                else
                {
                    // it's a rename
                    session.rename( dn, newRdn, entry.isDeleteOldRdn() );
                }

                break;

            case ( ChangeType.MODIFY_ORDINAL ):
                session.modify( dn, entry.getModifications() );
                break;

            default:
                throw new IllegalStateException( I18n.err( I18n.ERR_476, entry.getChangeType() ) );
        }
    }


    public static LdifEntry getUserAddLdif( String dnstr, byte[] password, String cn, String sn )
        throws LdapException
    {
        Dn dn = new Dn( dnstr );
        LdifEntry ldif = new LdifEntry();
        ldif.setDn( dnstr );
        ldif.setChangeType( ChangeType.Add );

        Attribute attr = new DefaultAttribute( "objectClass",
            "top", "person", "organizationalPerson", "inetOrgPerson" );
        ldif.addAttribute( attr );

        attr = new DefaultAttribute( "ou", "Engineering", "People" );
        ldif.addAttribute( attr );

        String uid = dn.getRdn().getValue();
        ldif.putAttribute( "uid", uid );

        ldif.putAttribute( "l", "Bogusville" );
        ldif.putAttribute( "cn", cn );
        ldif.putAttribute( "sn", sn );
        ldif.putAttribute( "mail", uid + "@apache.org" );
        ldif.putAttribute( "telephoneNumber", "+1 408 555 4798" );
        ldif.putAttribute( "facsimileTelephoneNumber", "+1 408 555 9751" );
        ldif.putAttribute( "roomnumber", "4612" );
        ldif.putAttribute( "userPassword", password );

        String givenName = cn.split( " " )[0];
        ldif.putAttribute( "givenName", givenName );

        return ldif;
    }


    // -----------------------------------------------------------------------
    // Enable/Disable Schema Tests
    // -----------------------------------------------------------------------

    public static void enableSchema( DirectoryService service, String schemaName ) throws LdapException
    {
        LdapConnection connection = getAdminConnection( service );

        // now enable the test schema
        connection.modify( "cn=" + schemaName + ",ou=schema",
            new DefaultModification(
                ModificationOperation.REPLACE_ATTRIBUTE, "m-disabled", "FALSE" ) );
    }


    public static void disableSchema( DirectoryService service, String schemaName ) throws LdapException
    {
        LdapConnection connection = getAdminConnection( service );

        // now enable the test schema
        Modification mod = new DefaultModification(
            ModificationOperation.REPLACE_ATTRIBUTE, "m-disabled", "TRUE" );

        connection.modify( "cn=" + schemaName + ",ou=schema", mod );
    }


    /**
     * A helper method which tells if a schema is disabled.
     * 
     * @param service The Directory Service 
     * @param schemaName The name of the Schema to check
     * @return <tt>true</tt> if the schema is enabled
     */
    public static boolean isDisabled( DirectoryService service, String schemaName )
    {
        Schema schema = service.getSchemaManager().getLoadedSchema( schemaName );

        return ( schema == null ) || schema.isDisabled();
    }


    /**
     * A helper method which tells if a schema is loaded.
     * 
     * @param service The Directory Service 
     * @param schemaName The schema to check
     * @return <tt>true</tt> if the schema is loaded
     */
    public static boolean isLoaded( DirectoryService service, String schemaName )
    {
        Schema schema = service.getSchemaManager().getLoadedSchema( schemaName );

        return ( schema != null );
    }


    /**
     * A helper method which tells if a schema is enabled. A shema must be
     * loaded and enabled.
     * 
     * @param service The Directory Service 
     * @param schemaName The name of the Schema to check
     * @return <tt>true</tt> if the schema is enabled
     */
    public static boolean isEnabled( DirectoryService service, String schemaName )
    {
        Schema schema = service.getSchemaManager().getLoadedSchema( schemaName );

        return ( schema != null ) && schema.isEnabled();
    }


    /**
     * Gets a LdapCoreSessionConnection bound using the default admin Dn uid=admin,ou=system and password "secret"
     * 
     * @param dirService The Directory Service to be connected to
     * @return A LdapCoreSessionConnection instance
     * @exception LdapException If the connection could not be established.
     */
    public static LdapConnection getAdminConnection( DirectoryService dirService ) throws LdapException
    {
        return getConnectionAs( dirService, ServerDNConstants.ADMIN_SYSTEM_DN, "secret" );
    }


    /**
     * Gets a LdapCoreSessionConnection bound using a user's DN and a password. We will bind using those
     * credentials.
     * 
     * @param dirService The Directory Service to be connected to
     * @param dn The User's DN as a String
     * @param password The User's password as a String
     * @return A LdapCoreSessionConnection instance
     * @exception LdapException If the connection could not be established.
     */
    public static LdapConnection getConnectionAs( DirectoryService dirService, String dn, String password )
        throws LdapException
    {
        return getConnectionAs( dirService, new Dn( dn ), password );
    }


    /**
     * Gets a LdapCoreSessionConnection bound using a user's DN and a password. We will bind using those
     * credentials.
     * 
     * @param dirService The Directory Service to be connected to
     * @param dn The User's DN
     * @param password The User's password as a String
     * @return A LdapCoreSessionConnection instance
     * @exception LdapException If the connection could not be established.
     */
    public static LdapConnection getConnectionAs( DirectoryService dirService, Dn dn, String password )
        throws LdapException
    {
        LdapCoreSessionConnection connection = new LdapCoreSessionConnection();

        connection.setDirectoryService( dirService );

        connection.bind( dn, password );

        return connection;
    }


    /**
     * Gets a LdapNetworkConnection bound using a user's DN and a password. We will bind using those
     * credentials.
     * 
     * @param host The server to connect to
     * @param port The port to connect on
     * @param dn The User's DN as a String
     * @param password The User's password as a String
     * @return A LdapNetworkConnection instance
     * @exception LdapException If the connection could not be established.
     */
    public static LdapConnection getNetworkConnectionAs( String host, int port, String dn, String password )
        throws LdapException
    {
        LdapConnection connection = new LdapNetworkConnection( host, port );

        connection.bind( dn, password );
        OPEN_CONNECTIONS.add( connection );
        
        return connection;
    }


    /**
     * Gets an anonymous LdapNetworkConnection
     * 
     * @param ldapServer The LdapServer to be connected to
     * @return A LdapNetworkConnection instance
     * @exception LdapException If the connection could not be established.
     */
    public static LdapConnection getAnonymousNetworkConnection( LdapServer ldapServer ) throws LdapException
    {
        return getAnonymousNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() );
    }


    /**
     * Gets an anonymous LdapNetworkConnection
     * 
     * @param host The server to connect to
     * @param port The port to connect on
     * @return A LdapNetworkConnection instance
     * @exception LdapException If the connection could not be established.
     */
    public static LdapConnection getAnonymousNetworkConnection( String host, int port ) throws LdapException
    {
        LdapConnection connection = new LdapNetworkConnection( host, port );
        connection.bind();

        OPEN_CONNECTIONS.add( connection );

        return connection;
    }


    /**
     * Gets a LdapNetworkConnection bound to the Admin user (uid=admin,ou=system).
     * 
     * @param ldapServer The LdapServer to be connected to
     * @return A LdapNetworkConnection instance
     * @exception LdapException If the connection could not be established.
     */
    public static LdapConnection getAdminNetworkConnection( LdapServer ldapServer ) throws LdapException
    {
        LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, ldapServer.getPort() );

        connection.setTimeOut( 30000L );
        connection.bind( ServerDNConstants.ADMIN_SYSTEM_DN, "secret" );

        OPEN_CONNECTIONS.add( connection );

        return connection;
    }


    /**
     * Gets a LdapNetworkConnection bound using a user's DN and a password. We will bind using those
     * credentials. We specify a LdapServer instance too.
     * 
     * @param ldapServer The LdapServer to be connected to
     * @param userDn The User's DN as a String
     * @param password The User's password as a String
     * @return A LdapNetworkConnection instance
     * @exception LdapException If the connection could not be established.
     */
    public static LdapConnection getNetworkConnectionAs( LdapServer ldapServer, String userDn, String password )
        throws LdapException
    {
        return getNetworkConnectionAs( Network.LOOPBACK_HOSTNAME, ldapServer.getPort(), userDn, password );
    }


    public static void closeConnections()
    {

        for ( LdapConnection con : OPEN_CONNECTIONS )
        {
            if ( con == null )
            {
                continue;
            }

            try
            {
                if ( con.isConnected() )
                {
                    con.close();
                }
            }
            catch ( Exception e )
            {
                // shouldn't happen, but print the stacktrace so that less pain during development to find the cause
                e.printStackTrace();
            }
        }

        OPEN_CONNECTIONS.clear();
    }
}
