/++
  native headers using<br>@title:<BR>:subtitle:<BR>type tags<BR>
  extract native/orig header return associative array
+/
template SiSUheaderExtractNative() {
  private import
    std.exception,
    std.regex,
    std.utf,
    std.conv : to;
  private import
    ao_rgx;
  struct HeaderDocMetadataAndMakeNativeToAA {
    mixin SiSUregisters;
    mixin SiSUrgxInitFlags;
    mixin RgxInit;
    auto rgx = Rgx();
    enum State { off, on }
    string hm, hs;
    auto header_metadata_and_make_aa(
      string header,
      string[string][string] dochead_meta,
      string[string][string] dochead_make
    )
    in { }
    body {
      scope(exit) {
        destroy(header);
        destroy(dochead_meta);
        destroy(dochead_make);
      }
      if (auto t = match(header, rgx.native_header_main)) {
        char[][] header_obj_spl = split(
          cast(char[]) header,
          rgx.line_delimiter_ws_strip
        );
        auto hm = to!string(t.captures[1]);
        if (match(hm, rgx.main_headers)) {
          foreach (line; header_obj_spl) {
            if (auto m = match(line, rgx.native_header_main)) {
              if (!empty(m.captures[2])) {
                if (hm == "creator") {
                  dochead_meta[hm]["author"] =
                    to!string(m.captures[2]);
                } else if (hm == "title") {
                  dochead_meta[hm]["main"] =
                    to!string(m.captures[2]);
                } else if (hm == "publisher") {
                  dochead_meta[hm]["name"] =
                    to!string(m.captures[2]);
                }
              }
            } else if (auto s = match(line, rgx.native_header_sub)) {
              if (!empty(s.captures[2])) {
                auto hs = to!string(s.captures[1]);
                if ((hm == "make" )
                && (dochead_make[hm])) {
                  switch (hm) {
                  case "make":
                    if (match(hs, rgx.native_subhead_make)) {
                      if (dochead_make[hm][hs]) {
                        dochead_make[hm][hs] = to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  default:
                    break;
                  }
                } else if (dochead_meta[hm]) {
                  switch (hm) {
                  case "creator":
                    if (match(hs, rgx.native_subhead_creator)) {
                      if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "title":
                    if (match(hs, rgx.native_subhead_title)) {
                      if ((hs == "subtitle")
                      && (dochead_meta[hm]["sub"])) {
                        dochead_meta[hm]["sub"] =
                          to!string(s.captures[2]);
                      } else if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "rights":
                    if (match(hs, rgx.native_subhead_rights)) {
                      if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "date":
                    if (match(hs, rgx.native_subhead_date)) {
                      if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "original":
                    if (match(hs, rgx.native_subhead_original)) {
                      if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "classify":
                    if (match(hs, rgx.native_subhead_classify)) {
                      if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "identifier":
                    if (match(hs, rgx.native_subhead_identifier)) {
                      if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "notes":
                    if (match(hs, rgx.native_subhead_notes)) {
                      if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "publisher":
                    if (match(hs, rgx.native_subhead_publisher)) {
                      if (dochead_meta[hm][hs]) {
                        dochead_meta[hm][hs] =
                          to!string(s.captures[2]);
                      }
                    } else {
                      writeln("not a valid header type:", hm, ":", hs);
                      destroy(hm);
                      destroy(hs);
                    }
                    break;
                  case "links":
                    destroy(hm);
                    destroy(hs);
                    break;
                  default:
                    break;
                  }
                }
              }
            }
          }
        } else {
          writeln("not a valid header type:", hm);
        }
      }
      auto t = tuple(dochead_meta, dochead_make);
      static assert(t.length==2);
      return t;
    }
    private auto native_header_extract(
      char[] line,
      ref int[string] line_occur,
      ref string[string] an_object,
      ref int[string] type
    ) {
      if (matchFirst(line, rgx.native_header_make)) {   /+ matched header_make +/
        debug(header1) { /+ writeln(line); +/ }
        type["header"]      = State.on;
        type["header_make"] = State.on;
        type["header_meta"] = State.off;
        ++line_occur["header_make"];
        an_object["body_nugget"] ~= line ~= "\n";
      } else if (matchFirst(line, rgx.native_header)) { /+ matched header_metadata +/
        /+ (generic header match and not previously caught by header_make) +/
        debug(header1) { /+ writeln(line); +/ }
        type["header"]      = State.on;
        type["header_make"] = State.off;
        type["header_meta"] = State.on;
        ++line_occur["header_meta"];
        an_object["body_nugget"] ~= line ~= "\n";
      } else if (type["header_make"] == State.on
      && (line_occur["header_make"] > State.off)) {     /+ header_make flag set +/
        if (matchFirst(line, rgx.native_header_sub)) {  /+ sub-header +/
          debug(header1) { /+ writeln(line); +/ }
          ++line_occur["header_make"];
          an_object["body_nugget"] ~= line ~= "\n";
        }
      } else if (type["header_meta"] == State.on
      && (line_occur["header_meta"] > State.off)) {     /+ header_metadata flag set +/
        if (matchFirst(line, rgx.native_header_sub)) {  /+ sub-header +/
          debug(header1) { /+ writeln(line); +/ }
          ++line_occur["header_meta"];
          an_object["body_nugget"] ~= line ~= "\n";
        }
      }
      return an_object;
    }
    auto header_reset_states_common(
      ref int[string] line_occur,
      ref string[string] an_object,
      ref int[string] type
    ) {
      line_occur["header_make"] = State.off;
      line_occur["header_meta"] = State.off;
      type["header"] = State.off;
      an_object.remove("body_nugget");
      an_object.remove("is");
      an_object.remove("attrib");
    }
    private auto headerNativeToAA(in char[] src_header) {
      auto type = flags_type_init;
      type = [
       "header"          : State.off,
       "header_make"     : State.off,
       "header_meta"     : State.off,
      ];
      string[string] an_object;
      int[string] line_occur;
      auto dochead_make = make_aa;
      auto dochead_meta = meta_aa;
      auto set_header = HeaderDocMetadataAndMakeNativeToAA();
      char[][] source_header_arr =
        split(cast(char[]) src_header, rgx.newline_eol_delimiter);
      foreach(header_line; source_header_arr) {
        if (auto m = matchFirst(header_line, rgx.comment)) {
          /+ matched comment +/
          debug(comment) {
          }
          header_reset_states_common(line_occur, an_object, type);
        } else if ((matchFirst(header_line, rgx.native_header))
        || (type["header_make"] == State.on
        && (line_occur["header_make"] > State.off))
        || (type["header_meta"] == State.on
        && (line_occur["header_meta"] > State.off))) {
          if (header_line.length == 0) {
            /+ header_make instructions (current line empty) +/
            auto dochead_metadata_and_make =
              set_header.header_metadata_and_make_aa(strip(an_object["body_nugget"]), dochead_meta, dochead_make);
            static assert(!isTypeTuple!(dochead_metadata_and_make));
            dochead_meta = dochead_metadata_and_make[0];
            dochead_make = dochead_metadata_and_make[1];
            header_reset_states_common(line_occur, an_object, type);
            type["header_make"] = State.off;
            type["header_meta"] = State.off;
            debug(headersdlang) {
              writeln(dochead_metadata_and_make);
            }
          } else {
            an_object = native_header_extract(header_line, line_occur, an_object, type);
          }
        }
      }
      auto t = tuple(
        dochead_make,
        dochead_meta,
      );
      return t;
    }
  }
}