package org.geotools.feature.iso.xpath;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.commons.jxpath.ri.QName;
import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
import org.apache.commons.jxpath.ri.model.NodeIterator;
import org.apache.commons.jxpath.ri.model.NodePointer;
import org.geotools.feature.iso.Types;
import org.geotools.resources.Utilities;
import org.opengis.feature.Attribute;
import org.opengis.feature.ComplexAttribute;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.Name;

/**
 * Special node iterator for {@link Attribute}.
 * 
 * @author Justin Deoliveira, The Open Planning Project
 * @author Gabriel Roldan, Axios Engineering
 *
 */
public class AttributeNodeIterator implements NodeIterator {

	/**
	 * The feature node pointer
	 */
	AttributeNodePointer pointer;
	/**
	 * The feature.
	 */
	ComplexAttribute feature;
    
    List children;
    
	/**
	 * current position
	 */
	int position;
	
	public AttributeNodeIterator( AttributeNodePointer pointer ) {
		this.pointer = pointer;
		feature = (ComplexAttribute) pointer.getImmediateNode();
        children = new ArrayList((Collection)feature.getValue());
		position = 1;
	}
    
    public AttributeNodeIterator( AttributeNodePointer pointer, NodeNameTest filter ) {
        this.pointer = pointer;
        feature = (ComplexAttribute) pointer.getImmediateNode();

        String localName = filter.getNodeName().getName();
        String nameSpace = filter.getNamespaceURI();
        
        AttributeDescriptor descriptor = feature.getDescriptor();
        Name attName = descriptor == null? feature.getType().getName() : descriptor.getName();
        if(Utilities.equals(nameSpace, attName.getNamespaceURI()) && 
                Utilities.equals(localName, attName.getLocalPart())){
            children = Collections.singletonList(feature);
        }else{
            Name name = Types.typeName(nameSpace, localName);
            children = feature.get(name);
        }
        
        position = children.size() > 0? 1 : 0;
    }
	
	public int getPosition() {
		return position;
	}

	public boolean setPosition(int position) {
		this.position = position;
		return position <= children.size();
	}

	public NodePointer getNodePointer() {
		Attribute attribute = (Attribute) children.get(position - 1);
        Name name = attribute.getDescriptor().getName();
        QName qname = new QName(name.getNamespaceURI(), name.getLocalPart());
        return new AttributeNodePointer(pointer, attribute, qname);
	}

}
