open Ocamlbuild_plugin;;
open Ocamlbuild_pack;;
open Command;;

let ocamlducedep_command arg =
	let tags = tags_of_pathname arg++"ocaml"++"ocamldep" in
	if Tags.does_match tags (Tags.of_list ["use_ocamlduce"]) then
		S[A "ocamlducefind"; A "ocamldep"; T tags; Ocaml_utils.ocaml_ppflags tags; Tools.flags_of_pathname arg; A "-modules"]
	else
		S[!Options.ocamldep; T tags; Ocaml_utils.ocaml_ppflags tags; Tools.flags_of_pathname arg; A "-modules"];;

let ocamlducedep_command arg out =
	S[ocamlducedep_command arg; P arg; Sh ">"; Px out];;

dispatch begin function
	| Before_options ->
		begin
			Options.ocamlc := S[A "ocamlfind"; A "ocamlc"];
			Options.ocamlopt := S[A "ocamlfind"; A "ocamlopt"];
			Options.ocamldep := S[A "ocamlfind"; A "ocamldep"];
			Options.ocamlyacc := S[A "menhir" (* ; A "--trace" *)];
		end
	| After_rules ->
		Ocamldep.depends "ocamlduce dependencies ml" ~insert:(`before "ocaml dependencies ml") ~ocamldep_command:ocamlducedep_command ~dep:"%.ml" ~prod:"%.ml.depends" ();

		Ocamldep.depends "ocamlduce dependencies mli" ~insert:(`before "ocaml dependencies mli") ~ocamldep_command:ocamlducedep_command ~dep:"%.mli" ~prod:"%.mli.depends" ();

		rule "ocamlduce: ml & cmi -> cmo" ~insert:(`before "ocaml: ml & cmi -> cmo") ~prod:"%.cmo" ~deps:["%.mli"; "%.ml"; "%.ml.depends"; "%.cmi"] 
		begin fun env build ->
			let ml = env "%.ml"
			and _cmo = env "%.cmo" in
			let tags = (tags_of_pathname ml)++"compile"++"ocaml"++"byte" in
			Ocaml_compiler.prepare_compile build ml;
			if Tags.does_match tags (Tags.of_list ["use_ocamlduce"]) then
				Cmd(S[A "ocamlducefind"; A "ocamlc"; A "-c"; Ocaml_utils.ocaml_include_flags ml; T tags; P ml])
			else
				Cmd(S[!Options.ocamlc; A "-c"; Ocaml_utils.ocaml_include_flags ml; T tags; P ml])
		end;

		rule "ocamlduce: ml -> cmo & cmi" ~insert:(`before "ocaml: ml -> cmo & cmi") ~prods:["%.cmo"; "%.cmi"] ~deps:["%.ml"; "%.ml.depends"]
		begin fun env build ->
			let ml = env "%.ml"
			and cmo = env "%.cmo" in
			let tags = (tags_of_pathname ml)++"compile"++"ocaml"++"byte" in
			Ocaml_compiler.prepare_compile build ml;
			if Tags.does_match tags (Tags.of_list ["use_ocamlduce"]) then
				Cmd(S[A "ocamlducefind"; A "ocamlc"; A "-c"; Ocaml_utils.ocaml_include_flags ml; T tags; A "-o"; P cmo; P ml])
			else
				Cmd(S[!Options.ocamlc; A "-c"; Ocaml_utils.ocaml_include_flags ml; T tags; P ml])
		end;

	  rule "ocamlduce: cmo* -> cma" ~insert:(`before "ocaml: cmo* -> cma") ~prod:"%.cma" ~dep:"%.cmo"
		begin fun env _build ->
			let cmo = env "%.cmo"
			and cma = env "%.cma" in
			let tags = (tags_of_pathname cmo)++"library"++"ocaml"++"byte" in
			if Tags.does_match tags (Tags.of_list ["use_ocamlduce"]) then
				Cmd(S[A "ocamlducefind"; A "ocamlc"; A "-a"; Ocaml_utils.ocaml_include_flags cmo; T tags; A "-o"; P cma; P cmo])
			else
				Cmd(S[!Options.ocamlc; A "-a"; T tags; Ocaml_utils.ocaml_include_flags cmo; A "-o"; P cma; P cmo])
		end;

		flag ["byte"; "camlp4o"] (S[A "-pp"; A "camlp4o.byte"]);
		flag ["compile"; "use_calendar"] (S[A "-package"; A "calendar"]);
		flag ["compile"; "use_pcre"] (S[A "-package"; A "pcre"]);
		flag ["compile"; "use_ocsigen"] (S[A "-package"; A "ocsigen"]);
		flag ["program"; "use_calendar"] (S[A "-linkpkg"; A "-package"; A "calendar"]);
		flag ["program"; "use_pcre"] (S[A "-linkpkg"; A "-package"; A "pcre"]);
	| _ -> ()
end;;
