(**************************************************************************)
(*                                                                        *)
(*  Copyright (C) Johannes Kanig, Stephane Lescuyer                       *)
(*  Jean-Christophe Filliatre, Romain Bardou and Francois Bobot           *)
(*                                                                        *)
(*  This software is free software; you can redistribute it and/or        *)
(*  modify it under the terms of the GNU Library General Public           *)
(*  License version 2.1, with the special exception on linking            *)
(*  described in file LICENSE.                                            *)
(*                                                                        *)
(*  This software 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.                  *)
(*                                                                        *)
(**************************************************************************)

# 18 "myocamlbuild.ml.in"
open Ocamlbuild_plugin
open Command

let tagcairo = ref false
let tagconcrete = ref false

let packages_cairo = ["cairo","@CAIROLIB@","cairo"; ]

let packages () =
  let acc =
    [
      "lablgtk2","@LABLGTK2LIB@","lablgtk";
      "lablgnomecanvas","@LABLGTK2LIB@","lablgnomecanvas"; ] in
  if !tagconcrete then
    ("bitstring","@BITSTRINGLIB@","bitstring") :: acc
  else acc

let gen_def_string () =
  let l = [] in
  let l = if !tagconcrete then "-D CONCRETE" :: l else l in
  let l = if !tagcairo then "-D CAIRO"::l else l in
  l

let string_flatten l = List.fold_left (fun acc s -> acc ^ " " ^ s) "" l

let syntaxes () =
  let bitstring_entry =
    let cmd = "@CAMLP4O@ -I @BITSTRINGLIB@ bitstring.cma \
                bitstring_persistent.cma pa_bitstring.cmo" in
     "bitstring", cmd, cmd in
  let s = string_flatten (gen_def_string ()) in
  let compile_cmd = "@CAMLP4O@ Camlp4MacroParser.cmo " ^ s in
  let doc_cmd = "./myocamlmacroparser.native " ^ s in
  let mymacroparser_entry = "mymacroparser",compile_cmd, doc_cmd in
  let macro_entry = "macro", compile_cmd, compile_cmd in
  [ bitstring_entry ; mymacroparser_entry ; macro_entry ]

let img_doc_prod = ["circle";"rect";"ellipse";"round_rect";
                    "patatoid";"tex";"ctr";"north";"south";
                    "west";"east";"north_west";"south_west";
                    "north_east";"south_east";"width";"height";
                    "shift";"center";"halign"; "hplace"; "hbox";
                   ]

let _ = dispatch begin function
  | Before_options ->
      Options.include_dirs :=
        "concrete"::"dvi"::"backend"::"gui"::!Options.include_dirs;
      Options.exclude_dirs :=
        "presentations"::"papers"::"examples"::
          "contrib/dot/_build"::"contrib/lablgtk/_build"::
          "test"::!Options.exclude_dirs;
      Options.ocamldoc := S[A"@OCAMLDOC@"]
  | Before_rules ->
      tagcairo := Ocamlbuild_pack.Configuration.has_tag "cairo_yes";
      tagconcrete := Ocamlbuild_pack.Configuration.has_tag "concrete_yes";
      let yesnofile_rule file yesno ext =
        rule (file^" generation for "^yesno)
          ~deps:[file^yesno^ext] ~prod:(file^ext)
          (fun _ _ -> cp (file^yesno^ext) (file^ext)) in
      if !tagcairo then begin
        yesnofile_rule "mlpost" "_cairo" ".mlpack";
      end else begin
        if !tagconcrete then begin
          yesnofile_rule "mlpost" "_concrete" ".mlpack";
        end else begin
          yesnofile_rule "mlpost" "_no" ".mlpack";
        end
      end;

      yesnofile_rule "mlpost" "_@LABLGTK2@lablgtk" ".odocl";

      let copy file1 file2 =
        rule (" copy from "^file1^"to "^file2)
          ~deps:[file1] ~prod:(file2)
          (fun _ _ -> cp file1 file2) in
      copy "contrib/dot/mlpost_dot.mli" "mlpost_dot.mli";
      copy "contrib/lablgtk/mlpost_lablgtk.mli" "mlpost_lablgtk.mli";

      (**doc *)
      rule "generation of the documentation" ~prod:"doc/index.html"
        ~deps:["mlpost.docdir/html.stamp";"img/stamp"]
         (fun _ _ ->
           Cmd(Sh "rm -rf doc && cp -r mlpost.docdir doc && cp -r img doc"));
      flag ["ocaml"; "compile"; "use_ocamldoc"] & S[A"-I"; A "+ocamldoc"];
      dep ["ocaml";"doc"] ["customdoc/img.cmo"];
      dep ["ocaml"; "syntax_mymacroparser"] ["myocamlmacroparser.native"];
      flag ["ocaml";"doc"] &
        S([A"-hide" ; A "Mlpost"; A"-g"; A "customdoc/img.cmo"]
            @ (if "@LABLGTK2@" = "yes"
               then [A"-I"; A"@LABLGTK2LIB@"]
               else []));

      rule "generation of the images for the documentation"
        ~prod:"img/image.png"
        ~stamp:"img/stamp"
        ~deps:(List.map (fun x -> "img/"^x^".png") img_doc_prod)
        (fun _ _ -> Nop);

       (** For img *)
      rule "produce image in img from img_doc.ml"
        ~prods: (List.map (fun x -> "img/"^x^".1") img_doc_prod)
        ~dep: "customdoc/img_doc.byte"
        begin fun env _ ->
           Cmd(Sh "mkdir -p img/ && cd img/ && ../customdoc/img_doc.byte \
                     >> /dev/null && cd ..")
        end;

       (** conversion of images *)
      rule ".1 -> .dvi"
        ~prod: "%.dvi"
        ~deps: ["%.1";"customdoc/all.template"]
        begin fun env _ ->
          let base = env "%" in
          let dirname = Pathname.dirname base in
          let basename = Pathname.basename base in
          let sed =
            Sh(Printf.sprintf
              "sed -e 's/all/%s/' customdoc/all.template > %s.tex"
              basename base) in
          let latex = S[
            A "cd" ; P dirname; Sh " && ";
            A "latex"; A "-interaction"; A "nonstopmode";
            A "-file-line-error"; A "-halt-on-error";
            A basename;
            Sh "> /dev/null"; (* DELETE THIS IF YOU WANT TO DEBUG *) ] in
          Seq[Cmd sed; Cmd latex]
        end;

      rule ".dvi -> .ps" ~prod: "%.ps" ~dep: "%.dvi" (fun env _ ->
          let base = env "%.dvi" in
          let dirname = Pathname.dirname base in
          let basename = Pathname.basename base in
          Cmd(S[A "cd" ; P dirname; Sh " && ";
                A "dvips"; A "-q"; A "-E"; A basename; A "-o"]));


      rule ".ps -> png" ~prod: "%.png" ~dep: "%.ps"
        (fun env _ -> Cmd(S[A "convert"; A(env "%.ps"); A(env "%.png")]));

  | After_rules ->
      if !tagcairo then
        ocaml_lib ~extern:true ~tag_name:("use_cairo_bigarray") "bigarray";

      List.iter (fun (pkg,dir,file) ->
        ocaml_lib ~extern:true ~tag_name:("pkg_"^pkg) ~dir file;
        flag ["ocaml"; "pack"; "pkg_"^pkg] & S[A"-I"; P dir];
        flag ["ocaml"; "doc"; "pkg_"^pkg ] & S[A"-I"; P dir])
        (let p = packages () in if !tagcairo then packages_cairo@p else p);

      List.iter (fun (syntax,pp, doc) ->
        flag ["ocaml"; "compile";  "syntax_"^syntax] & S[A"-pp"; A pp];
        flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-pp"; A pp];
        flag ["ocaml"; "doc";      "syntax_"^syntax] & S[A"-pp"; A doc];)
      (syntaxes ());
   | _ -> ()
end
