/*
 * Copyright 1999-2000 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package com.sun.jndi.toolkit.dir;

import javax.naming.*;
import javax.naming.directory.SearchControls;
import java.util.*;

/**
  * A class for recursively enumerating the contents of a Context;
  *
  * @author Jon Ruiz
  */
public class ContextEnumerator implements NamingEnumeration {

    private static boolean debug = false;
    private NamingEnumeration children = null;
    private Binding currentChild = null;
    private boolean currentReturned = false;
    private Context root;
    private ContextEnumerator currentChildEnum = null;
    private boolean currentChildExpanded = false;
    private boolean rootProcessed = false;
    private int scope = SearchControls.SUBTREE_SCOPE;
    private String contextName = "";

    public ContextEnumerator(Context context) throws NamingException {
        this(context, SearchControls.SUBTREE_SCOPE);
    }

    public ContextEnumerator(Context context, int scope)
        throws NamingException {
            // return this object except when searching single-level
        this(context, scope, "", scope != SearchControls.ONELEVEL_SCOPE);
   }

    protected ContextEnumerator(Context context, int scope, String contextName,
                             boolean returnSelf)
        throws NamingException {
        if(context == null) {
            throw new IllegalArgumentException("null context passed");
        }

        root = context;

        // No need to list children if we're only searching object
        if (scope != SearchControls.OBJECT_SCOPE) {
            children = getImmediateChildren(context);
        }
        this.scope = scope;
        this.contextName = contextName;
        // pretend root is processed, if we're not supposed to return ourself
        rootProcessed = !returnSelf;
        prepNextChild();
    }

    // Subclass should override if it wants to avoid calling obj factory
    protected NamingEnumeration getImmediateChildren(Context ctx)
        throws NamingException {
            return ctx.listBindings("");
    }

    // Subclass should overrride so that instance is of same type as subclass
    protected ContextEnumerator newEnumerator(Context ctx, int scope,
        String contextName, boolean returnSelf) throws NamingException {
            return new ContextEnumerator(ctx, scope, contextName, returnSelf);
    }

    public boolean hasMore() throws NamingException {
        return !rootProcessed ||
            (scope != SearchControls.OBJECT_SCOPE && hasMoreDescendants());
    }

    public boolean hasMoreElements() {
        try {
            return hasMore();
        } catch (NamingException e) {
            return false;
        }
    }

    public Object nextElement() {
        try {
            return next();
        } catch (NamingException e) {
            throw new NoSuchElementException(e.toString());
        }
    }

    public Object next() throws NamingException {
        if (!rootProcessed) {
            rootProcessed = true;
            return new Binding("", root.getClass().getName(),
                               root, true);
        }

        if (scope != SearchControls.OBJECT_SCOPE && hasMoreDescendants()) {
            return getNextDescendant();
        }

        throw new NoSuchElementException();
    }

    public void close() throws NamingException {
        root = null;
    }

    private boolean hasMoreChildren() throws NamingException {
        return children != null && children.hasMore();
    }

    private Binding getNextChild() throws NamingException {
        Binding oldBinding = ((Binding)children.next());
        Binding newBinding = null;

        // if the name is relative, we need to add it to the name of this
        // context to keep it relative w.r.t. the root context we are
        // enumerating
        if(oldBinding.isRelative() && !contextName.equals("")) {
            NameParser parser = root.getNameParser("");
            Name newName = parser.parse(contextName);
            newName.add(oldBinding.getName());
            if(debug) {
                System.out.println("ContextEnumerator: adding " + newName);
            }
            newBinding = new Binding(newName.toString(),
                                     oldBinding.getClassName(),
                                     oldBinding.getObject(),
                                     oldBinding.isRelative());
        } else {
            if(debug) {
                System.out.println("ContextEnumerator: using old binding");
            }
            newBinding = oldBinding;
        }

        return newBinding;
    }

    private boolean hasMoreDescendants() throws NamingException {
        // if the current child is expanded, see if it has more elements
        if (!currentReturned) {
            if(debug) {System.out.println("hasMoreDescendants returning " +
                                          (currentChild != null) ); }
            return currentChild != null;
        } else if (currentChildExpanded && currentChildEnum.hasMore()) {

            if(debug) {System.out.println("hasMoreDescendants returning " +
                "true");}

            return true;
        } else {
            if(debug) {System.out.println("hasMoreDescendants returning " +
                "hasMoreChildren");}
            return hasMoreChildren();
        }
    }

    private Binding getNextDescendant() throws NamingException {

        if (!currentReturned) {
            // returning parent
            if(debug) {System.out.println("getNextDescedant: simple case");}

            currentReturned = true;
            return currentChild;

        } else if (currentChildExpanded && currentChildEnum.hasMore()) {

            if(debug) {System.out.println("getNextDescedant: expanded case");}

            // if the current child is expanded, use it's enumerator
            return (Binding)currentChildEnum.next();

        } else {

            // Ready to go onto next child
            if(debug) {System.out.println("getNextDescedant: next case");}

            prepNextChild();
            return getNextDescendant();
        }
    }

    private void prepNextChild() throws NamingException {
        if(hasMoreChildren()) {
            try {
                currentChild = getNextChild();
                currentReturned = false;
            } catch (NamingException e){
                if (debug) System.out.println(e);
                if (debug) e.printStackTrace();
            }
        } else {
            currentChild = null;
            return;
        }

        if(scope == SearchControls.SUBTREE_SCOPE &&
           currentChild.getObject() instanceof Context) {
            currentChildEnum = newEnumerator(
                                          (Context)(currentChild.getObject()),
                                          scope, currentChild.getName(),
                                          false);
            currentChildExpanded = true;
            if(debug) {System.out.println("prepNextChild: expanded");}
        } else {
            currentChildExpanded = false;
            currentChildEnum = null;
            if(debug) {System.out.println("prepNextChild: normal");}
        }
    }
}
