package eu.dnetlib.functionality.cql;

import java.util.List;

import org.z3950.zing.cql.CQLAndNode;
import org.z3950.zing.cql.CQLBooleanNode;
import org.z3950.zing.cql.CQLNode;
import org.z3950.zing.cql.CQLNotNode;
import org.z3950.zing.cql.CQLOrNode;
import org.z3950.zing.cql.CQLPrefixNode;
import org.z3950.zing.cql.CQLTermNode;

public class CqlFilter {

	public CQLNode filter(final CQLNode node, final List<String> fields) {
		return doFilter(node, fields);
	}

	private CQLNode doFilter(CQLNode node, List<String> fields) {

		if (node instanceof CQLBooleanNode) {
			return doFilter((CQLBooleanNode) node, fields);
		}

		if (node instanceof CQLTermNode) {
			return doFilter((CQLTermNode) node, fields);
		}
		
		if (node instanceof CQLPrefixNode) {
			return node;
		}		

		if (node == null) {
			return null;
		}

		throw new RuntimeException("error choice");
	}

	private CQLNode doFilter(CQLBooleanNode node, List<String> fields) {

		CQLNode left = doFilter(node.left, fields);
		CQLNode right = doFilter(node.right, fields);

		if (left == null && right == null) {
			return null;
		}

		if (left == null) {
			return right;
		}

		if (right == null) {
			return left;
		}

		if (node instanceof CQLAndNode) {
			return new CQLAndNode(left, right, node.ms);
		}

		if (node instanceof CQLOrNode) {
			return new CQLOrNode(left, right, node.ms);
		}

		if (node instanceof CQLNotNode) {
			return new CQLNotNode(left, right, node.ms);
		}

		throw new RuntimeException("unknow boolean node");
	}

	private static CQLNode doFilter(CQLTermNode node, List<String> fields) {
		return isTermNodeToFilter(node, fields) ? null : node;
	}

	private static boolean isTermNodeToFilter(CQLTermNode node, List<String> fields) {
		return fields.contains(node.getIndex().toLowerCase());
	}

}
