/**
 * Modern Albufeira Prolog Interpreter
 *
 * Warranty & Liability
 * To the extent permitted by applicable law and unless explicitly
 * otherwise agreed upon, XLOG Technologies AG makes no warranties
 * regarding the provided information. XLOG Technologies AG assumes
 * no liability that any problems might be solved with the information
 * provided by XLOG Technologies AG.
 *
 * Rights & License
 * All industrial property rights regarding the information - copyright
 * and patent rights in particular - are the sole property of XLOG
 * Technologies AG. If the company was not the originator of some
 * excerpts, XLOG Technologies AG has at least obtained the right to
 * reproduce, change and translate the information.
 *
 * Reproduction is restricted to the whole unaltered document. Reproduction
 * of the information is only allowed for non-commercial uses. Selling,
 * giving away or letting of the execution of the library is prohibited.
 * The library can be distributed as part of your applications and libraries
 * for execution provided this comment remains unchanged.
 *
 * Restrictions
 * Only to be distributed with programs that add significant and primary
 * functionality to the library. Not to be distributed with additional
 * software intended to replace any components of the library.
 *
 * Trademarks
 * Jekejeke is a registered trademark of XLOG Technologies AG.
 */

/*******************************************************************/
/* Bundler JavaScript                                              */
/*******************************************************************/

% bundle_begin(+Atom)
bundle_begin(OutName) :-
   setup_once_cleanup(
      open(OutName, write, OutStream),
      true,
      close(OutStream)).

/**
 * bundle_add(A, B):
 * bundle_add(A, B, O):
 * The predicate succeeds in appending the JavaScript file
 * A to the JavaScript file B, converting JavaScript imports.
 * The bundler silently overwrites an already existing JavaScript
 * file B. The ternary predicate allows specifying bundle options.
 */
% bundle_add(+Atom, +Atom)
bundle_add(InName, OutName) :-
   bundle_add(InName, OutName, []).

% bundle_add(+Atom, +Atom, +List)
bundle_add(InName, OutName, Opt) :-
   decode_bundle_opts(Opt, 0, Flags),
   setup_once_cleanup(
      open(OutName, append, OutStream),
      bundle_file(InName, OutStream, Flags),
      close(OutStream)).

/**
 * bundle_file(A, S, F):
 * Copy the file A into the stream S, converting JavaScript
 * to JavaScript determined by the flags F.
 */
% bundle_file(+Atom, +Stream, +Integer)
bundle_file(InName, OutStream, Flags) :-
   setup_once_cleanup(
      open(InName, read, InStream),
      sys_bundle_lines(InStream, OutStream, Flags),
      close(InStream)).

% sys_bundle_lines(+Stream, +Stream, +Integer)
sys_bundle_lines(InStream, OutStream, Flags) :-
   repeat,
   get_atom(InStream, Line, []),
   (Line \== '' ->
      sys_bundle_line(Line, Line2, InStream, Flags),
      write(OutStream, Line2), fail; !).

% sys_bundle_line(+Atom, -Atom, +Stream, +Integer)
sys_bundle_line(Line, _, InStream, _) :-
   atom_concat('/*', _, Line), !,
   (Line2 = Line; enum_atoms(InStream, Line2)),
   atom_concat(_, '*/\n', Line2), !, fail.
/* export handling */
sys_bundle_line(Line, Line2, _, Flags) :- Flags /\ 1 =:= 0,
   atom_concat('export ', B, Line), !,
   B = Line2.
/* import handling */
sys_bundle_line(Line, _, InStream, Flags) :- Flags /\ 4 =:= 0,
   atom_concat('import ', _, Line), !,
   (Line2 = Line; enum_atoms(InStream, Line2)),
   atom_concat(_, ';\n', Line2), !, fail.
sys_bundle_line(Line, Line, _, _).

/*******************************************************************/
/* Decode Bundle Options                                           */
/*******************************************************************/

% decode_bundle_opts(+List, +Integer, -Integer)
decode_bundle_opts(V, _, _) :- var(V),
   throw(error(instantiation_error,_)).
decode_bundle_opts([X|L], I, O) :- !,
   decode_bundle_opt(X, I, H),
   decode_bundle_opts(L, H, O).
decode_bundle_opts([], H, H) :- !.
decode_bundle_opts(L, _, _) :-
   throw(error(type_error(list,L),_)).

% decode_bundle_opt(+Option, +Triple, -Triple)
decode_bundle_opt(V, _, _) :- var(V),
   throw(error(instantiation_error,_)).
decode_bundle_opt(keep_export(B), F, G) :- !,
   sys_opt_boolean(B, 1, F, G).
decode_bundle_opt(keep_import(B), F, G) :- !,
   sys_opt_boolean(B, 4, F, G).
decode_bundle_opt(O, _, _) :-
   throw(error(type_error(bundle_option,O),_)).