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


import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.directory.mavibot.btree.serializer.ElementSerializer;


/**
 * A BTree builder that builds a tree from the bottom.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class PersistedBTreeBuilder<K, V>
{
    private String name;

    private int numKeysInNode;

    private ElementSerializer<K> keySerializer;

    private ElementSerializer<V> valueSerializer;

    private RecordManager rm;


    public PersistedBTreeBuilder( RecordManager rm, String name, int numKeysInNode, ElementSerializer<K> keySerializer,
        ElementSerializer<V> valueSerializer )
    {
        this.rm = rm;
        this.name = name;
        this.numKeysInNode = numKeysInNode;
        this.keySerializer = keySerializer;
        this.valueSerializer = valueSerializer;
    }


    @SuppressWarnings("unchecked")
    public BTree<K, V> build( Iterator<Tuple<K, V>> sortedTupleItr ) throws Exception
    {
        BTree<K, V> btree = BTreeFactory.createPersistedBTree( name, keySerializer, valueSerializer );

        rm.manage( btree );

        List<Page<K, V>> lstLeaves = new ArrayList<Page<K, V>>();

        int totalTupleCount = 0;

        PersistedLeaf<K, V> leaf1 = ( PersistedLeaf<K, V> ) BTreeFactory.createLeaf( btree, 0, numKeysInNode );
        lstLeaves.add( leaf1 );

        int leafIndex = 0;

        while ( sortedTupleItr.hasNext() )
        {
            Tuple<K, V> tuple = sortedTupleItr.next();

            BTreeFactory.setKey( btree, leaf1, leafIndex, tuple.getKey() );

            PersistedValueHolder<V> eh = new PersistedValueHolder<V>( btree, tuple.getValue() );

            BTreeFactory.setValue( btree, leaf1, leafIndex, eh );

            leafIndex++;
            totalTupleCount++;
            if ( ( totalTupleCount % numKeysInNode ) == 0 )
            {
                leafIndex = 0;

                PageHolder<K, V> pageHolder = rm.writePage( btree, leaf1, 1 );

                leaf1 = ( PersistedLeaf<K, V> ) BTreeFactory.createLeaf( btree, 0, numKeysInNode );
                lstLeaves.add( leaf1 );
            }

            //TODO build the whole tree in chunks rather than processing *all* leaves at first
        }

        if ( lstLeaves.isEmpty() )
        {
            return btree;
        }

        // remove null keys and values from the last leaf and resize
        PersistedLeaf<K, V> lastLeaf = ( PersistedLeaf<K, V> ) lstLeaves.get( lstLeaves.size() - 1 );
        for ( int i = 0; i < lastLeaf.getNbElems(); i++ )
        {
            if ( lastLeaf.getKey( i ) == null )
            {
                int n = i;
                lastLeaf.setNbElems( n );
                KeyHolder<K>[] keys = lastLeaf.getKeys();

                lastLeaf.setKeys( ( KeyHolder[] ) Array.newInstance( PersistedKeyHolder.class, n ) );
                System.arraycopy( keys, 0, lastLeaf.getKeys(), 0, n );

                ValueHolder<V>[] values = lastLeaf.values;
                lastLeaf.values = ( PersistedValueHolder<V>[] ) Array.newInstance( PersistedValueHolder.class, n );
                System.arraycopy( values, 0, lastLeaf.values, 0, n );

                PageHolder<K, V> pageHolder = rm.writePage( btree, lastLeaf, 1 );

                break;
            }
        }

        // make sure either one of the root pages is reclaimed, cause when we call rm.manage()
        // there is already a root page created
        Page<K, V> rootPage = attachNodes( lstLeaves, btree );

        //System.out.println("built rootpage : " + rootPage);
        ( ( PersistedBTree<K, V> ) btree ).setNbElems( totalTupleCount );

        rm.updateBtreeHeader( btree, ( ( AbstractPage<K, V> ) rootPage ).getOffset() );

        rm.addFreePages( btree, Arrays.asList( btree.getRootPage() ) );

        ( ( AbstractBTree<K, V> ) btree ).setRootPage( rootPage );

        return btree;
    }


    @SuppressWarnings("unchecked")
    private Page<K, V> attachNodes( List<Page<K, V>> children, BTree<K, V> btree ) throws IOException
    {
        if ( children.size() == 1 )
        {
            return children.get( 0 );
        }

        List<Page<K, V>> lstNodes = new ArrayList<Page<K, V>>();

        int numChildren = numKeysInNode + 1;

        PersistedNode<K, V> node = ( PersistedNode<K, V> ) BTreeFactory.createNode( btree, 0, numKeysInNode );
        lstNodes.add( node );
        int i = 0;
        int totalNodes = 0;

        for ( Page<K, V> page : children )
        {
            if ( i != 0 )
            {
                BTreeFactory.setKey( btree, node, i - 1, page.getLeftMostKey() );
            }

            BTreeFactory.setPage( btree, node, i, page );

            i++;
            totalNodes++;

            if ( ( totalNodes % numChildren ) == 0 )
            {
                i = 0;

                PageHolder<K, V> pageHolder = rm.writePage( btree, node, 1 );

                node = ( PersistedNode<K, V> ) BTreeFactory.createNode( btree, 0, numKeysInNode );
                lstNodes.add( node );
            }
        }

        // remove null keys and values from the last node and resize
        AbstractPage<K, V> lastNode = ( AbstractPage<K, V> ) lstNodes.get( lstNodes.size() - 1 );

        for ( int j = 0; j < lastNode.getNbElems(); j++ )
        {
            if ( lastNode.getKey( j ) == null )
            {
                int n = j;
                lastNode.setNbElems( n );
                KeyHolder<K>[] keys = lastNode.getKeys();

                lastNode.setKeys( ( KeyHolder[] ) Array.newInstance( KeyHolder.class, n ) );
                System.arraycopy( keys, 0, lastNode.getKeys(), 0, n );

                PageHolder<K, V> pageHolder = rm.writePage( btree, lastNode, 1 );

                break;
            }
        }

        return attachNodes( lstNodes, btree );
    }
}
