/*
 * 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.partition.impl.btree.jdbm;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;

import jdbm.RecordManager;
import jdbm.helper.DefaultSerializer;
import jdbm.helper.IntegerSerializer;
import jdbm.recman.BaseRecordManager;

import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.cursor.Cursor;
import org.apache.directory.api.ldap.model.cursor.Tuple;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.ldap.model.schema.comparators.SerializableComparator;
import org.apache.directory.api.ldap.schemaextractor.SchemaLdifExtractor;
import org.apache.directory.api.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
import org.apache.directory.api.ldap.schemaloader.LdifSchemaLoader;
import org.apache.directory.api.ldap.schemamanager.impl.DefaultSchemaManager;
import org.apache.directory.api.util.exception.Exceptions;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Tests JdbmTable operations with duplicates.  Does not test Cursor capabilities.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class JdbmTableWithDuplicatesTest
{
    private static final Logger LOG = LoggerFactory.getLogger( JdbmTableWithDuplicatesTest.class );
    private static final String TEST_OUTPUT_PATH = "test.output.path";
    private static final int SIZE = 15;
    private static final int SIZE2 = 30;

    private static final String SIZE_MINUS_ONE_STR = "14";
    private static final String SIZE_STR = "15";
    private static final String SIZE_PLUS_ONE_STR = "16";

    private static final String SIZE2_MINUS_ONE_STR = "29";
    private static final String SIZE2_STR = "30";
    private static final String SIZE2_PLUS_ONE_STR = "31";

    JdbmTable<String, String> table;
    File dbFile;
    RecordManager recman;
    private static SchemaManager schemaManager;


    @BeforeClass
    public static void init() throws Exception
    {
        String workingDirectory = System.getProperty( "workingDirectory" );

        if ( workingDirectory == null )
        {
            String path = DupsContainerCursorTest.class.getResource( "" ).getPath();
            int targetPos = path.indexOf( "target" );
            workingDirectory = path.substring( 0, targetPos + 6 );
        }

        File schemaRepository = new File( workingDirectory, "schema" );
        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
        extractor.extractOrCopy( true );
        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
        schemaManager = new DefaultSchemaManager( loader );

        boolean loaded = schemaManager.loadAllEnabled();

        if ( !loaded )
        {
            fail( "Schema load failed : " + Exceptions.printErrors( schemaManager.getErrors() ) );
        }
    }


    @Before
    public void createTable() throws Exception
    {
        destroyTable();
        File tmpDir = null;

        if ( System.getProperty( TEST_OUTPUT_PATH, null ) != null )
        {
            tmpDir = new File( System.getProperty( TEST_OUTPUT_PATH ) );
        }

        dbFile = File.createTempFile( getClass().getSimpleName(), "db", tmpDir );
        recman = new BaseRecordManager( dbFile.getAbsolutePath() );

        SerializableComparator<String> comparator = new SerializableComparator<String>(
            SchemaConstants.INTEGER_ORDERING_MATCH_MR_OID );
        comparator.setSchemaManager( schemaManager );

        table = new JdbmTable<String, String>( schemaManager, "test", SIZE, recman,
            comparator, comparator, new DefaultSerializer(), new DefaultSerializer() );
        LOG.debug( "Created new table and populated it with data" );
    }


    @After
    public void destroyTable() throws Exception
    {
        if ( table != null )
        {
            table.close();
        }

        table = null;

        if ( recman != null )
        {
            recman.close();
        }

        recman = null;

        if ( dbFile != null )
        {
            String fileToDelete = dbFile.getAbsolutePath();
            new File( fileToDelete + ".db" ).delete();
            new File( fileToDelete + ".lg" ).delete();

            dbFile.delete();
        }

        dbFile = null;
    }


    @Test
    public void testSerializers() throws Exception
    {
        assertNotNull( table.getKeySerializer() );
        assertNotNull( ( ( JdbmTable<?, ?> ) table ).getValueSerializer() );
    }


    @Test
    public void testCountOneArg() throws Exception
    {
        assertEquals( 0, table.count( "3" ) );
        assertEquals( 0, table.count( null ) );
    }


    @Test(expected = IllegalArgumentException.class)
    public void testNullKeyComparator() throws Exception
    {
        assertNotNull( table.getKeyComparator() );

        SerializableComparator<String> comparator = new SerializableComparator<String>(
            SchemaConstants.INTEGER_ORDERING_MATCH_MR_OID );
        comparator.setSchemaManager( schemaManager );

        new JdbmTable<String, String>( schemaManager, "test", SIZE, recman,
            null, comparator, null, new IntegerSerializer() );
    }


    @Test(expected = IllegalArgumentException.class)
    public void testNullValueComparator() throws Exception
    {
        assertNotNull( table.getValueComparator() );

        SerializableComparator<String> comparator = new SerializableComparator<String>(
            SchemaConstants.INTEGER_ORDERING_MATCH_MR_OID );
        comparator.setSchemaManager( schemaManager );

        new JdbmTable<String, String>( schemaManager, "test", SIZE, recman,
            comparator, null, null, new IntegerSerializer() );
    }


    @Test
    public void testCloseReopen() throws Exception
    {
        table.put( "1", "2" );
        assertEquals( "2", table.get( "1" ) );
        table.close();
        SerializableComparator<String> comparator = new SerializableComparator<String>(
            SchemaConstants.INTEGER_ORDERING_MATCH_MR_OID );
        comparator.setSchemaManager( schemaManager );

        table = new JdbmTable<String, String>( schemaManager, "test", SIZE, recman,
            comparator, comparator, new DefaultSerializer(), new DefaultSerializer() );
        assertEquals( "2", table.get( "1" ) );
    }


    @Test
    public void testConfigMethods() throws Exception
    {
        assertTrue( table.isDupsEnabled() );
        assertEquals( "test", table.getName() );
        assertNotNull( table.getKeyComparator() );
    }


    @Test
    public void testWhenEmpty() throws Exception
    {
        // Test the count methods
        assertEquals( 0, table.count() );
        assertEquals( 0, table.count( "1" ) );

        // Test get method
        assertNull( table.get( "0" ) );
        assertNull( table.get( null ) );

        // Test remove methods
        table.remove( "1" );
        assertFalse( table.has( "1" ) );

        // Test has operations
        assertFalse( table.has( "1" ) );
        assertFalse( table.has( "1", "0" ) );
        assertFalse( table.hasGreaterOrEqual( "1" ) );
        assertFalse( table.hasLessOrEqual( "1" ) );
        assertFalse( table.hasGreaterOrEqual( "1", "0" ) );
        assertFalse( table.hasLessOrEqual( "1", "0" ) );
    }


    @Test
    public void testPut() throws Exception
    {
        final int SIZE = 15;

        for ( int i = 0; i < SIZE; i++ )
        {
            String istr = Integer.toString( i );
            table.put( istr, istr );
        }

        assertEquals( SIZE, table.count() );
        table.put( "0", "0" );
        assertTrue( table.has( "0", "0" ) );

        // add some duplicates
        for ( int i = 0; i < SIZE * 2; i++ )
        {
            String istr = Integer.toString( i );
            table.put( SIZE2_STR, istr );
        }

        assertEquals( SIZE * 3, table.count() );

        table.put( "0", "0" );
        assertTrue( table.has( "0", "0" ) );

        table.put( SIZE2_STR, "0" );
        assertTrue( table.has( SIZE2_STR, "0" ) );
    }


    @Test
    public void testHas() throws Exception
    {
        assertFalse( table.has( "1" ) );

        for ( int i = 0; i < SIZE * 2; i++ )
        {
            String istr = Integer.toString( i );
            table.put( "1", istr );
        }

        assertEquals( SIZE2, table.count() );

        assertTrue( table.has( "1" ) );
        assertTrue( table.has( "1", "0" ) );
        assertFalse( table.has( "1", SIZE2_STR ) );

        assertTrue( table.hasGreaterOrEqual( "1", "0" ) );
        assertTrue( table.hasLessOrEqual( "1", "0" ) );
        assertFalse( table.hasLessOrEqual( "1", "-1" ) );

        assertTrue( table.hasGreaterOrEqual( "1", SIZE2_MINUS_ONE_STR ) );
        assertTrue( table.hasLessOrEqual( "1", SIZE2_MINUS_ONE_STR ) );
        assertTrue( table.hasGreaterOrEqual( "1", SIZE2_MINUS_ONE_STR ) );
        assertTrue( table.hasLessOrEqual( "1", SIZE2_STR ) );
        assertFalse( table.hasGreaterOrEqual( "1", SIZE2_STR ) );
        assertFalse( table.has( "1", SIZE2_STR ) );

        // let's go over the this limit now and ask the same questions
        table.put( "1", SIZE2_STR );

        assertTrue( table.has( "1" ) );
        assertTrue( table.has( "1", "0" ) );
        assertTrue( table.has( "1", SIZE2_STR ) );
        assertFalse( table.has( null, null ) );

        assertTrue( table.hasGreaterOrEqual( "1", "0" ) );
        assertTrue( table.hasLessOrEqual( "1", "0" ) );
        assertFalse( table.hasLessOrEqual( "1", "-1" ) );
        assertFalse( table.hasGreaterOrEqual( null, null ) );
        assertFalse( table.hasLessOrEqual( null, null ) );

        assertTrue( table.hasGreaterOrEqual( "1", SIZE2_STR ) );
        assertTrue( table.hasLessOrEqual( "1", SIZE2_STR ) );
        assertTrue( table.hasGreaterOrEqual( "1", SIZE2_STR ) );
        assertTrue( table.hasLessOrEqual( "1", SIZE2_STR ) );
        assertFalse( table.hasGreaterOrEqual( "1", SIZE2_PLUS_ONE_STR ) );
        assertFalse( table.has( "1", SIZE2_PLUS_ONE_STR ) );

        // now do not add duplicates and check has( key, boolean )
        for ( int i = 0; i < SIZE; i++ )
        {
            // note we are not adding duplicates not put( 1, i )
            String istr = Integer.toString( i );
            table.put( istr, istr );
        }

        assertFalse( table.has( "-1" ) );
        assertTrue( table.hasGreaterOrEqual( "-1" ) );
        assertFalse( table.hasLessOrEqual( "-1" ) );

        assertTrue( table.has( "0" ) );
        assertTrue( table.hasGreaterOrEqual( "0" ) );
        assertTrue( table.hasLessOrEqual( "0" ) );

        assertTrue( table.has( SIZE_MINUS_ONE_STR ) );
        assertTrue( table.hasGreaterOrEqual( SIZE_MINUS_ONE_STR ) );
        assertTrue( table.hasLessOrEqual( SIZE_MINUS_ONE_STR ) );

        assertFalse( table.has( SIZE_STR ) );
        assertFalse( table.hasGreaterOrEqual( SIZE_STR ) );
        assertTrue( table.hasLessOrEqual( SIZE_STR ) );

        for ( int i = 0; i < SIZE; i++ )
        {
            if ( i == 1 ) // don't delete the node which had multiple values
            {
                continue;
            }

            String istr = Integer.toString( i );
            table.remove( istr, istr );
        }

        // delete all values of the duplicate key one by one
        for ( int i = 0; i < SIZE * 2 + 1; i++ )
        {
            String istr = Integer.toString( i );
            table.remove( "1", istr );
        }

        Cursor<Tuple<String, String>> cursor = table.cursor();

        cursor.beforeFirst();

        while ( cursor.next() )
        {
            //System.out.println( cursor.get() );
        }

        cursor.close();

        assertFalse( table.hasLessOrEqual( "1" ) );
        assertFalse( table.hasLessOrEqual( "1", "10" ) );
        assertFalse( table.hasGreaterOrEqual( "1" ) );
        assertFalse( table.hasGreaterOrEqual( "1", "0" ) );

        table.put( "1", "0" );

    }


    @Test
    public void testRemove() throws Exception
    {
        assertEquals( 0, table.count() );

        table.put( "1", "1" );
        table.put( "1", "2" );
        assertEquals( 2, table.count() );
        table.remove( "1" );
        assertFalse( table.has( "1" ) );
        assertEquals( 0, table.count() );

        table.put( "10", "10" );
        assertEquals( 1, table.count() );
        table.remove( "10", "11" );
        assertFalse( table.has( "10", "11" ) );
        assertEquals( 1, table.count() );
        table.remove( "10", "10" );
        assertFalse( table.has( "10", "10" ) );
        assertEquals( 0, table.count() );

        // add duplicates
        for ( int i = 0; i < SIZE * 2; i++ )
        {
            String istr = Integer.toString( i );
            table.put( "0", istr );
        }

        assertEquals( SIZE * 2, table.count() );
        table.remove( "0", "100" );
        assertFalse( table.has( "0", "100" ) );
        assertEquals( SIZE * 2, table.count() );

        table.remove( "0" );
        assertNull( table.get( "0" ) );
    }


    @Test
    public void testLoadData() throws Exception
    {
        // add some data to it
        for ( int i = 0; i < SIZE; i++ )
        {
            String istr = Integer.toString( i );
            table.put( istr, istr );
        }

        assertEquals( 15, table.count() );
        assertEquals( 1, table.count( "0" ) );

        /*
         * If counts are exact then we can test for exact values.  Again this 
         * is not a critical function but one used for optimization so worst 
         * case guesses are allowed.
         */

        assertEquals( 10, table.lessThanCount( "5" ) );
        assertEquals( 10, table.greaterThanCount( "5" ) );
    }


    @Test
    public void testDuplicateLimit() throws Exception
    {
        assertFalse( table.isKeyUsingBTree( "1" ) );

        for ( int i = 0; i < SIZE; i++ )
        {
            String istr = Integer.toString( i );
            table.put( "1", istr );
        }
        assertEquals( SIZE, table.count() );
        assertEquals( SIZE, table.count( "1" ) );
        assertFalse( table.isKeyUsingBTree( "1" ) );

        // this switches to B+Trees from AvlTree
        table.put( "1", SIZE_STR );
        assertEquals( SIZE + 1, table.count() );
        assertEquals( SIZE + 1, table.count( "1" ) );
        assertTrue( table.isKeyUsingBTree( "1" ) );

        // go one more over still a B+Tree
        table.put( "1", SIZE_PLUS_ONE_STR );
        assertEquals( SIZE + 2, table.count() );
        assertEquals( SIZE + 2, table.count( "1" ) );
        assertEquals( "0", table.get( "1" ) );
        assertTrue( table.isKeyUsingBTree( "1" ) );

        // now start removing and see what happens 
        table.remove( "1", SIZE_PLUS_ONE_STR );
        assertFalse( table.has( "1", SIZE_PLUS_ONE_STR ) );
        assertTrue( table.has( "1", SIZE_STR ) );
        assertEquals( SIZE + 1, table.count() );
        assertEquals( SIZE + 1, table.count( "1" ) );
        assertTrue( table.isKeyUsingBTree( "1" ) );

        // this switches to AvlTree from B+Trees
        table.remove( "1", SIZE_STR );
        assertFalse( table.has( "1", SIZE_STR ) );
        assertEquals( SIZE, table.count() );
        assertEquals( SIZE, table.count( "1" ) );
        assertEquals( "0", table.get( "1" ) );
        assertFalse( table.isKeyUsingBTree( "1" ) );

        for ( int i = SIZE - 1; i >= 0; i-- )
        {
            String istr = Integer.toString( i );
            table.remove( "1", istr );
            assertFalse( table.isKeyUsingBTree( "1" ) );
        }

        assertEquals( 0, table.count() );

        for ( int i = 0; i < SIZE - 1; i++ )
        {
            String istr = Integer.toString( i );
            table.put( "1", istr );
            assertFalse( table.isKeyUsingBTree( "1" ) );
        }

        // this switches back to using B+Trees from AvlTree
        table.put( "1", SIZE_STR );
        table.put( "1", SIZE_PLUS_ONE_STR );
        assertTrue( table.isKeyUsingBTree( "1" ) );

        assertEquals( SIZE + 1, table.count() );
        table.remove( "1" );
        assertEquals( 0, table.count() );
    }


    /**
     * Let's test keys with a null or lack of any values.
     * @throws Exception on error
     */
    @Test
    public void testNullOrEmptyKeyValueAfterDuplicateLimit() throws Exception
    {
        testDuplicateLimit();
        assertEquals( 0, table.count() );

        try
        {
            table.put( "1", null );
            fail( "should never get here due to IllegalArgumentException" );
        }
        catch ( IllegalArgumentException e )
        {
            assertNotNull( e );
        }

        try
        {
            table.put( null, "1" );
            fail( "should never get here due to IllegalArgumentException" );
        }
        catch ( IllegalArgumentException e )
        {
            assertNotNull( e );
        }

        assertEquals( 0, table.count() );
        assertEquals( null, table.get( "1" ) );

        // Let's add the key with two valid values and remove all values
        table.remove( "1" );
        table.put( "1", "1" );
        table.put( "1", "2" );
        assertEquals( 2, table.count( "1" ) );
        table.remove( "1", "1" );
        assertEquals( 1, table.count( "1" ) );
        assertEquals( "2", table.get( "1" ) );

        table.remove( "1", "2" );
        assertNull( table.get( "1" ) );
        assertEquals( 0, table.count( "1" ) );
        assertFalse( table.has( "1" ) );
    }


    @Test
    public void testMiscellaneous() throws Exception
    {
        assertNotNull( table.getMarshaller() );
        table.close();

        // test value btree creation without serializer
        SerializableComparator<String> comparator = new SerializableComparator<String>(
            SchemaConstants.INTEGER_ORDERING_MATCH_MR_OID );
        comparator.setSchemaManager( schemaManager );

        table = new JdbmTable<String, String>( schemaManager, "test", SIZE, recman,
            comparator, comparator, new DefaultSerializer(), null );
        assertNull( table.getValueSerializer() );

        for ( int i = 0; i < SIZE + 1; i++ )
        {
            String istr = Integer.toString( i );
            table.put( "0", istr );
        }

        table.remove( "0" );
        assertFalse( table.has( "0" ) );
    }


    /**
     * Let's test keys with a null or lack of any values.
     * @throws Exception on error
     */
    @Test
    public void testNullOrEmptyKeyValue() throws Exception
    {
        assertEquals( 0, table.count() );

        try
        {
            table.put( "1", null );
            fail( "should never get here due to IllegalArgumentException" );
        }
        catch ( IllegalArgumentException e )
        {
            assertNotNull( e );
        }

        try
        {
            table.put( null, "2" );
            fail( "should never get here due to IllegalArgumentException" );
        }
        catch ( IllegalArgumentException e )
        {
            assertNotNull( e );
        }

        assertEquals( 0, table.count() );
        assertEquals( null, table.get( "1" ) );

        // Let's add the key with two valid values and remove all values
        table.remove( "1" );
        table.put( "1", "1" );
        table.put( "1", "2" );
        assertEquals( 2, table.count( "1" ) );
        table.remove( "1", "1" );
        assertEquals( 1, table.count( "1" ) );
        assertEquals( "2", table.get( "1" ) );

        table.remove( "1", "2" );
        assertNull( table.get( "1" ) );
        assertEquals( 0, table.count( "1" ) );
        assertFalse( table.has( "1" ) );
    }
}
