/* -*- Mode: Prolog -*- */
/** @copyright
  
  This file is part of PrologDoc (http://prologdoc.sourceforge.net/).

  Copyright (C) 2004 by Salvador Fandino (sfandino@@yahoo.com)

  PrologDoc is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  PrologDoc 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 for more details.

  You should have received a copy of the GNU General Public License
  along with PrologDoc; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  @/copyright */

:- use_module(library('prologdoc/pd')).
:- use_module(library('prologdoc/pd_util'), [ la_reset/3,
					      la_get/2,
					      eas_get/2,
					      eas_reset/3 ]).

:- multifile
	autodoc_term/5,
	autodoc_directive/5.

:- export(autodoc_term(_,_,_,_,_)).

autodoc_term(':-'(Directive), E, E1, Q, Q1) :-
        !,
	autodoc_directive(Directive, E, E1, Q, Q1).
autodoc_term('-->'(Head, _), t(N, A, C), t(N, A, C1), Q, Q) :-
        !,
        functor(Head, Name, Arity),
	Arity1 is Arity + 2,
	merge_predicates([Name/Arity1], [], [dcg], C, C1).
autodoc_term(':-'(Head,_), t(N, A, C), t(N, A, C1), Q, Q) :-
        !,
        functor(Head, Name, Arity),
        merge_predicates([Name/Arity], [], [], C, C1).
autodoc_term(Fact, t(N, A, C), t(N, A, C1), Q, Q) :-
        functor(Fact, Name, Arity),
        merge_predicates([Name/Arity], [], [], C, C1).
autodoc_directive((A, B), E, E, Q, [':-'(A), ':-'(B) |Q]).
autodoc_directive(';'(A, _), E, E, Q, [':-'(A)|Q]).
autodoc_directive([F|More], E, E, Q, [consult(F), More |Q]).
autodoc_directive([], E, E, Q, Q).
autodoc_directive(module(Name, Exp), t(N, A, C), t(N, A1, C1), Q, Q) :-
	la_reset(A, $module=Name, A2),
	la_reset(A2, $exports=Exp, A1),
	merge_predicates(Exp, [], [public], C, C1).
autodoc_directive(use_module(Name), t(N, A, C), t(N, A, [t($consult, [$type = module, $name=Name], []) |C]), Q, Q).

autodoc_directive(consult(File), t(N, A, C), t(N, A, [t($consult, CA, []) | C]), Q, Q) :-
	(   File = library(Name)
	->  CA = [$type=library, $name=Name]
	;   (   File =.. [_,_|_]
	    ->	CA = [$type=external_library, $name=File]
	    ;	CA = [$type=file, $name=File] ) ).
autodoc_directive(export(P), t(N, A, C), t(N, A, C1), Q, Q) :-
	functor(P, Name, Arity),
	merge_predicates([Name/Arity], [], [public], C, C1).
autodoc_directive(dynamic(Dyn), t(N, A, C), t(N, A, C1), Q, Q) :-
	commas_to_list(Dyn, List),
	merge_predicates(List, [], [dynamic], C, C1).
autodoc_directive(multifile(MF), t(N, A, C), t(N, A, C1), Q, Q) :-
	commas_to_list(MF, List),
	merge_predicates(List, [], [multifile], C, C1).

commas_to_list((A, B), [A|T]) :-
	!,
	commas_to_list(B, T).
commas_to_list(A, [A]).

select_element_by_args([F|More], Req, E, Rest) :-
	(   eas_get(F, Req)
	->  E = F,
	    Rest = More
	;   Rest = [F|Rest1],
	    select_element_by_args(More, Req, E, Rest1) ).

merge_predicate_props([], E, E).
merge_predicate_props([P|More], t(N, A, C), E1) :-
	(   member(E, C),
	    match_tag(t(prop, [name=P], []), E)
	->  C1 = C
	;   C1 = [t(prop, [name=P, $autodoc=1], [])|C] ),
	merge_predicate_props(More, t(N, A, C1), E1). 

merge_predicates([], _, _, C, C).
merge_predicates([N/A|More], AA, Props, C, C1) :-
	!,
	(   select_element_by_args(C, [name=N, arity=A], E, Rest)
	->  eas_reset(E, AA, E1),
	    merge_predicate_props(Props, E1, E2),
	    C2 = [E2|Rest]
	;   merge_predicate_props(Props, t(pred, [name=N, arity=A, $autodoc=true | AA], []), E2),
	    C2 = [E2|C] ),
	merge_predicates(More, AA, Props, C2, C1).
merge_predicates([_|More], AA, Props, C, C1)  :-
	% ignore extraneous things
	merge_predicates(More, AA, Props, C, C1).