#!/usr/bin/env rdmd
// [used by rdmd]
/+
  sdp
  sdp.d
+/
/+ sdp  sisu document parser +/
private import
  std.getopt,
  std.process,
  std.stdio,
  std.algorithm,
  std.array,
  std.container,
  std.exception,
  std.json,
  // std.path,
  std.range,
  std.regex,
  // std.stdio,
  std.string,
  std.traits,
  std.typecons,
  std.utf,
  // std.variant,
  std.conv : to;
/+ sdp  sisu document parser +/
import
  compile_time_info,            // compile_time_info.d
  ao_abstract_doc_source,       // ao_abstract_doc_source.d
  ao_defaults,                  // ao_defaults.d
  ao_read_source_files,         // ao_read_source_files.d
  ao_output_debugs,             // ao_output_debugs.d
  ao_rgx,                       // ao_rgx.d
  ao_ansi_colors;               // ao_ansi_colors.d
  // std.conv;
mixin(import("version.txt"));
mixin CompileTimeInfo;
mixin RgxInit;
void main(string[] args) {
  
  mixin SiSUheader;
  mixin SiSUbiblio;
  mixin SiSUrgxInitFlags;
  mixin SiSUmarkupRaw;
  mixin SiSUdocAbstraction;
  mixin SiSUoutputDebugs;
  mixin ScreenTxtColors;
  auto raw = MarkupRaw();
  auto abs = Abstraction();
  auto dbg = SDPoutputDebugs();
  /+
  struct DocumentParts {
    string[string][] contents;
    JSONValue[string] metadata_json;
    JSONValue[string] make_json;
    string[][string][string] bookindex_unordered_hashes;
    JSONValue[] biblio;
  }
  +/
  string[] fns_src;
  string flag_action;
  string arg_unrecognized;
  auto rgx = Rgx();
  scope(success) {
    debug(checkdoc) {
      writefln(
        "%s~ run complete, ok ~ %s (sdp-%s.%s.%s, %s v%s, %s %s)",
        scr_txt_color["cyan"], scr_txt_color["off"],
        ver.major, ver.minor, ver.patch,
        __VENDOR__, __VERSION__,
        bits, os,
      );
    }
    // stderr.writeln("0");
  }
  scope(failure) {
    debug(checkdoc) {
      stderr.writefln(
        "%s~ run failure ~%s",
         scr_txt_color["fuchsia"], scr_txt_color["off"],
      );
    }
  }
  
  bool[string] opt_action_bool = [
    "assertions"          : false,
    "html"                : false,
    "no_obj_cite_number"  : false,
    "verbose"             : false,
  ];
  auto helpInfo = getopt(args,
    std.getopt.config.passThrough,
    "assert",    "--assert set optional assertions on",          &opt_action_bool["assertions"],
    "html",      "--html process html output",                   &opt_action_bool["html"],
    "no-ocn",    "--no-ocn suppress object cite number output",  &opt_action_bool["no_obj_cite_number"],
    "verbose|v", "--verbose output to terminal",                 &opt_action_bool["verbose"],
  );
  if (helpInfo.helpWanted) {
    defaultGetoptPrinter("Some information about the program.", helpInfo.options);
  }
  foreach(arg; args) {
    if (match(arg, rgx.flag_action)) {
      flag_action ~= " " ~ arg;   // flags not taken by getopt
    } else if (match(arg, rgx.src_pth)) {
      fns_src ~= arg;             // gather input markup source file names for processing
    } else {                      // anything remaining, unused
      arg_unrecognized ~= " " ~ arg;
    }
  }
  foreach(fn_src; fns_src) {
    if (!empty(fn_src)) {
      scope(success) {
        debug(checkdoc) {
          writefln(
            "%s~ document complete, ok ~%s",
            scr_txt_color["green"], scr_txt_color["off"],
          );
        }
        // stderr.writeln("0");
      }
      scope(failure) {
        debug(checkdoc) {
          stderr.writefln(
            "%s~ document run failure ~%s (%s  v%s)\n\t%s",
            scr_txt_color["red"], scr_txt_color["off"],
            __VENDOR__, __VERSION__,
            fn_src
          );
        }
        // stderr.writeln("1");
      }
      enforce(
        match(fn_src, rgx.src_pth),
        "not a sisu markup filename"
      );
      /+ ↓ read file +/
      auto sourcefile_content =
        raw.sourceContent(fn_src);
      /+ ↓ porcess document, return abstraction as tuple +/
      auto t =
        abs.abstract_doc_source(sourcefile_content);
      static assert(!isTypeTuple!(t));
      auto doc_ao_contents = t[0]; // contents ~ endnotes ~ bookindex;
      // static assert(!isIterable!(doc_ao_contents));
      auto doc_ao_metadata_json = t[1];
      auto doc_ao_make_json = t[2];
      auto doc_ao_bookindex_unordered_hashes = t[3];
      auto doc_ao_biblio = t[4];
      // destroy(t);
      /+ ↓ document parts +/
      debug(checkdoc) { // checkbook & dumpdoc
        dbg.abstract_doc_source_debugs(
          doc_ao_contents,
          doc_ao_make_json,
          doc_ao_metadata_json,
          doc_ao_bookindex_unordered_hashes,
          doc_ao_biblio,
          fn_src,
          opt_action_bool
        );
      }
      scope(exit) {
        debug(checkdoc) {
          writefln(
            "processed file: %s",
            fn_src
          );
        }
        destroy(sourcefile_content);
        destroy(t);
        destroy(doc_ao_contents);
        destroy(doc_ao_make_json);
        destroy(doc_ao_metadata_json);
        destroy(doc_ao_bookindex_unordered_hashes);
        destroy(doc_ao_biblio);
        destroy(fn_src);
      }
    } else {
      /+ no recognized filename provided +/
      writeln("no recognized filename");
      break;
      // terminate, stop
    }
  }
}