package eu.dnetlib.data.collective.transformation.core.schema.visitor;


import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang3.NotImplementedException;
//import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;

import com.sun.xml.xsom.XSAnnotation;
import com.sun.xml.xsom.XSAttGroupDecl;
import com.sun.xml.xsom.XSAttributeDecl;
import com.sun.xml.xsom.XSAttributeUse;
import com.sun.xml.xsom.XSComplexType;
import com.sun.xml.xsom.XSContentType;
import com.sun.xml.xsom.XSElementDecl;
import com.sun.xml.xsom.XSFacet;
import com.sun.xml.xsom.XSIdentityConstraint;
import com.sun.xml.xsom.XSModelGroup;
import com.sun.xml.xsom.XSModelGroupDecl;
import com.sun.xml.xsom.XSNotation;
import com.sun.xml.xsom.XSParticle;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSimpleType;
import com.sun.xml.xsom.XSType;
import com.sun.xml.xsom.XSWildcard;
import com.sun.xml.xsom.XSXPath;
import com.sun.xml.xsom.visitor.XSVisitor;

import eu.dnetlib.data.collective.transformation.core.schema.SchemaAttribute;
import eu.dnetlib.data.collective.transformation.core.schema.SchemaElement;

/**
 * @author jochen
 *
 */
public class Visitor implements XSVisitor {
	
	//private static Log log = LogFactory.getLog(Visitor.class);
	List<SchemaElement> schemaElements = new LinkedList<SchemaElement>();
	SchemaElement currentElement;
	SchemaAttribute currentAttribute;
	
	@Override
	public void annotation(XSAnnotation arg0) {
		throw new NotImplementedException("TODO: annotation");
	}

	@Override
	public void attGroupDecl(XSAttGroupDecl arg0) {
		throw new NotImplementedException("TODO attGroupDecl");
	}

	@Override
	public void attributeDecl(XSAttributeDecl aAttributeDecl) {
		currentAttribute.setName(aAttributeDecl.getName());
		//log.debug("visit attribute name: " + aAttributeDecl.getName());
		//log.debug("visit attribute type: " + aAttributeDecl.getType());
		throw new NotImplementedException("TODO attributeDecl");
	}

	@Override
	public void attributeUse(XSAttributeUse aAttributeUse) {
		throw new NotImplementedException("TODO attributeUse");
	}

	@Override
	public void complexType(XSComplexType aType) {
		if (aType.getDerivationMethod()== XSType.RESTRICTION){
			XSContentTypeVisitorImpl contentTypeVisitor = new XSContentTypeVisitorImpl();
			contentTypeVisitor.setVisitor(this);
			aType.getContentType().visit(contentTypeVisitor);				
		}else{
			// aType.getExplicitContent().visit(this);
			throw new NotImplementedException("visiting types other then 'RESTRICTION are not implemented'");
		}
	}

	@Override
	public void facet(XSFacet arg0) {
		throw new NotImplementedException("TODO facet");
	}

	@Override
	public void identityConstraint(XSIdentityConstraint arg0) {
		throw new NotImplementedException("TODO identityConstraint");
	}

	@Override
	public void notation(XSNotation arg0) {
		throw new NotImplementedException("TODO notation");
	}

	@Override
	public void schema(XSSchema arg0) {
		throw new NotImplementedException("TODO schema");
	}

	@Override
	public void xpath(XSXPath arg0) {
		throw new NotImplementedException("TODO xpath");
	}

	@Override
	public void elementDecl(XSElementDecl aElementDecl) {
		XSType type = aElementDecl.getType();
		if (type.isLocal()){
			// complete infos about the current element
			// log.debug("visitor element name: " + aElementDecl.getName());
			currentElement.setName(aElementDecl.getName());
			currentElement.setTargetNamespace(aElementDecl.getTargetNamespace());
			type.visit(this);
		}
	}

	@Override
	public void modelGroup(XSModelGroup aGroup) {
		// a group of elements as childs of the root element
		for (XSParticle p: aGroup.getChildren()){
			particle(p);
		}
	}

	@Override
	public void modelGroupDecl(XSModelGroupDecl arg0) {
		throw new NotImplementedException("TODO modelGroupDecl");
	}

	@Override
	public void wildcard(XSWildcard arg0) {
		throw new NotImplementedException("TODO wildcard");
	}

	@Override
	public void empty(XSContentType arg0) {
		throw new NotImplementedException("TODO empty");
	}

	@Override
	public void particle(XSParticle aParticle) {
		// create a new schema element, add to the list of schema elements, set this element as current element
		SchemaElement element = new SchemaElement();
		element.setMinOccurs(aParticle.getMinOccurs().intValue());
		element.setMaxOccurs(aParticle.getMaxOccurs().intValue());
		element.setRepeatable(aParticle.isRepeated());
		schemaElements.add(element);
		currentElement = element;
		XSTermVisitorImpl termVisitor = new XSTermVisitorImpl();
		termVisitor.setVisitor(this);
		aParticle.getTerm().visit(termVisitor);
	}
 	
	
	@Override
	public void simpleType(XSSimpleType arg0) {
		throw new NotImplementedException("TODO simpleType");
	}
	
	public List<SchemaElement> getElements(){
		return this.schemaElements;
	}

	protected SchemaElement getCurrentElement(){
		return currentElement;
	}

}
