$:-consult(auxiliar).$
$:-consult(parser).$
$:-consult(aggregators).$

fuzzyXPath(_, [], _, _) <- {!} with tv(0,[]).
fuzzyXPath([], _, _, _) <- {!} with tv(0,[]).

fuzzyXPath([Label, attr(Atributo)], [element(Label, Attr, _)|Brothers], Deep, Down) <- {!} &prod
	    @fuse(
		attribute_values(Attr, Atributo),
		tv(0,[]),
		&prod(
			tv(Down,[]),
			fuzzyXPath([Label,attr(Atributo)], Brothers, Deep, Down)
		)).

fuzzyXPath([Label,tree(A,B,C)], [element(Label,Attr,Sons)|Brothers], Deep, Down) <- {!} &prod
	@fuse(
		@veri(
	    	    execute_fcond(Label, tree(A,B,C), element(Label,Attr,Sons)),
	    	    tv(0, [element(Label, Attr, Sons), [], []])),
		tv(0,[]),
	    	&prod(
		    tv(Down,[]),
		    fuzzyXPath([Label, tree(A,B,C)], Brothers, Deep, Down))).

fuzzyXPath(['',''|Label], [element(TagIam,Attr,Sons)|Brothers], Deep, Down) <- {!} &prod
	@fuse(
	    fuzzyXPath(Label, [element(TagIam,Attr,Sons)], Deep, Down),
	    &prod(
		tv(Deep,_),
		fuzzyXPath(['',''|Label], Sons, Deep, Down)),
	    &prod(
	        tv(Down,_),
		fuzzyXPath(['',''|Label], Brothers, Deep, Down))).

fuzzyXPath(['' | Path], In, Deep, Down) <-
	    fuzzyXPath(Path, In, Deep, Down) &prod {!}.

fuzzyXPath([Label|[]], [element(Label, Attr, Sons)|Brothers], Deep, Down)<- {!} &prod
	@fuse(
		tv(1, [element(Label, Attr, Sons), [], []]),
		tv(0,[]),
		&prod(
			tv(Down,[]),
			fuzzyXPath([Label|[]], Brothers, Deep, Down))).

fuzzyXPath([Label|[]], [_|Brothers], Deep, Down)<- {!} &prod
	@fuse(
		tv(1, []),
		tv(0,[]),
		&prod(
			tv(Down,[]),
			fuzzyXPath([Label|[]], Brothers, Deep, Down))).
fuzzyXPath([Label|LabelRest], [element(Label,_,Sons)|Brothers], Deep, Down)<-{!} &prod
	@fuse(
		tv(1, []),
		&prod(
			tv(Deep,[]),
			fuzzyXPath(LabelRest, Sons, Deep, Down)),
		&prod(
			tv(Down,[]),
			fuzzyXPath([Label|LabelRest], Brothers, Deep, Down))).

fuzzyXPath([Label|LabelRest], [_|Brothers], Deep, Down)<- {!} &prod
	@fuse(
		tv(1, []),
		tv(0,[]),
		&prod(
			tv(Down,[]),
			fuzzyXPath([Label|LabelRest], Brothers, Deep, Down))).

execute_fcond(Label, tree(and, T1, T2), element(Label,Attr,Sons))<- {!} &prod (
	                        execute_fcond(Label, T1, element(Label,Attr,Sons)) &prod
				execute_fcond(Label, T2, element(Label,Attr,Sons))).

execute_fcond(Label, tree(avg, T1, T2), element(Label,Attr,Sons))<- {!} &prod (
	                        execute_fcond(Label, T1, element(Label,Attr,Sons)) &prod
				execute_fcond(Label, T2, element(Label,Attr,Sons))).

execute_fcond(Label, tree(avg(A,B), T1, T2), element(Label,Attr,Sons))<- {!} &prod (
	                        execute_fcond(Label, T1, element(Label,Attr,Sons)) &prod
				execute_fcond(Label, T2, element(Label,Attr,Sons))).

execute_fcond(Label, tree(Exp,nil,nil), element(Label,Attr,Sons))<- {!} &prod
	                        execute_feq(Label, Exp, element(Label,Attr,Sons)).


execute_feq(Label, less(A,B), element(Label,Attr,_))<- {!} &prod 
	@cond_less(
		tv(1,[B,[],[]]),
		fuzzyXPath([Label, A], [element(Label, Attr, _)], 1, 1)). % devuelve listado con todos los valores encontrados

execute_feq(Label, greater(A,B), element(Label,Attr,_))<- {!} &prod 
	@cond_greater(
		tv(1,[B,[],[]]),
		fuzzyXPath([Label, A], [element(Label, Attr, _)], 1, 1)). % devuelve listado con todos los valores encontrados

execute_feq(Label, equal(A,B), element(Label,Attr,_))<- {!} &prod
	@cond_equal(
		tv(1,[B,[],[]]),
		fuzzyXPath([Label, A], [element(Label, Attr, _)], 1, 1)). % devuelve listado con todos los valores encontrados

attribute_values([],             _) <- {!} with tv(1, [element([], [], []), [], []]).
attribute_values(['='(Att,V)|RAtt], Att) <- {!} &prod
	                (@is(attribute_values(RAtt,Att),tv(1, [element(VR, [], []), [], []]))
			&prod {name(V,LV), name(NV,LV)}) with tv(1, [element([NV|VR], [], []), [], []]).
attribute_values([_|RAtt],Att) <- attribute_values(RAtt,Att).