/++
  sdlang headers<BR>
  extract sdlang header return sdlang
+/
template SiSUheaderExtractSDLang() {
  private import
    std.regex;
  private import
    ao_rgx;
  struct HeaderExtractSDL {
    mixin SiSUregisters;
    mixin RgxInit;
    auto rgx = Rgx();
    private auto sdlangToAAmake(string[string][string] conf, Tag conf_sdlang) {
      foreach (maintag, subtags; conf) {
        foreach (subtag, content; subtags) {
          if (!(conf_sdlang.maybe.tags[maintag].empty)) {
            if (!(conf_sdlang.tags[maintag][0].maybe.attributes[subtag].empty)
            && (conf_sdlang.tags[maintag][0].attributes[subtag][0].value.length > 0)) {
              debug(headersdlang) {
                writeln(conf_sdlang.tags[maintag][0].attributes[subtag][0].value);
              }
              conf[maintag][subtag] =
                to!string(conf_sdlang.tags[maintag][0].attributes[subtag][0].value);
            }
          }
        }
      }
      return conf;
    }
    private auto configSettingsSDLangToAAmake(Tag conf_sdlang) {
      auto conf = sdlangToAAmake(conf_aa, conf_sdlang);
      return conf;
    }
    private auto documentMakeSDLangToAAmake(Tag document_make_sdlang) {
      auto dochead_make = sdlangToAAmake(make_aa, document_make_sdlang);
      /+
      /+ dochead +/
      string hm;
      string hs;
      /+ make +/
      auto dochead_make = make_aa;
      if (!(document_make_sdlang.maybe.tags["make"].empty)) {
        hm = "make";
        hs = "bold";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "breaks";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "cover_image";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "css";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "emphasis";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "footer";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "headings";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "home_button_image";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "home_button_text";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "italics";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "num_top";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "substitute";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
        hs = "texpdf_font";
        if (!(document_make_sdlang.tags[hm][0].maybe.attributes[hs].empty)
        && (document_make_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
          debug(headersdlang) {
            writeln(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
          }
          dochead_make[hm][hs] =
            to!string(document_make_sdlang.tags[hm][0].attributes[hs][0].value);
        }
      }
      +/
      /+
      hm = "links";
      if (!(document_make_sdlang.maybe.tags[hm].empty)) {
        /+ TODO
          stuff to fix
        +/
      }
      +/
      return dochead_make;
    }
    final private auto headerMakeSDLang(in string src_header) {
      scope(failure) {
        stderr.writefln(
          "%s\n%s\n%s:%s failed here:\n  src_header: %s",
          __MODULE__, __FUNCTION__,
          __FILE__, __LINE__,
          src_header,
        );
      }
      Tag sdl_root_header;
      try {
        sdl_root_header = parseSource(src_header);
      }
      catch(ParseException e) {
        stderr.writeln("SDLang problem with this document header:");
        stderr.writeln(src_header);
        // Error messages of the form:
        // myFile.sdl(5:28): Error: Invalid integer suffix.
        stderr.writeln(e.msg);
      }
      debug(sdlang) {
        writeln("header SDL:");
        writeln(sdl_root_header.toSDLDocument());
      }
      return sdl_root_header;
    }
    private auto headerSDLangGet(in char[] src_header) {
      char[][] source_header_arr =
        split(cast(char[]) src_header, rgx.newline_eol_delimiter);
      char[] header_clean;
      // TODO
      foreach(header_line; source_header_arr) {
        if (!match(header_line, rgx.comments)) {
          header_clean ~= header_line ~ "\n";
        }
      }
      /+ get sdlang tags +/
      auto header_sdlang=headerMakeSDLang(to!string(header_clean));
      debug(sdlang) {
        writeln("--------------");
        stdout.rawWrite( header_sdlang.toSDLDocument() );
        writeln("--------------");
        Value test = header_sdlang.tags["title"][0].values[0];
        assert(test == typeid(string));
        writeln(header_sdlang.maybe.tags["title"]);
        writeln(header_sdlang.maybe.tags["title"][0].maybe.attributes["subtitle"]);
      }
      return header_sdlang; // sdlang.ast.Tag
    }
    private auto headerSDLangToAAmake(Tag header_sdlang, string[string][string] dochead_make) {
      dochead_make = sdlangToAAmake(dochead_make, header_sdlang);
      auto dochead_meta = sdlangToAAmake(meta_aa, header_sdlang);
      if (dochead_meta["title"]["main"].empty) {
        dochead_meta["title"]["main"] =
          to!string(header_sdlang.maybe.tags["title"][0].values[0]); // test that this exists
      }
      if (!(dochead_meta["title"]["subtitle"].empty)
      && (dochead_meta["title"]["sub"].empty)) {
        dochead_meta["title"]["sub"] ~= dochead_meta["title"]["subtitle"];
      }
      dochead_meta["title"].remove("subtitle");
      if (dochead_meta["title"]["sub"].empty) {
        dochead_meta["title"]["full"] ~= dochead_meta["title"]["main"];
      } else {
        dochead_meta["title"]["full"] ~= format(
          "%s - %s",
          dochead_meta["title"]["main"],
          dochead_meta["title"]["sub"],
        );
      }
      dochead_meta["creator"]["author_raw"] = dochead_meta["creator"]["author"];
      string[] authors_arr;
      auto authors_raw_arr = split(dochead_meta["creator"]["author"], rgx.arr_delimiter);
      foreach (author_raw; authors_raw_arr) {
        authors_arr ~= replace(author_raw, rgx.raw_author_munge, "$2 $1");
      }
      dochead_meta["creator"]["author"] = join(authors_arr, ", ").chomp.chomp;
      auto t = tuple(dochead_make, dochead_meta);
      static assert(t.length==2);
      return t;
    }
    private auto headerSDLangToAA(char[] header_sdlang_src, string[string][string] conf_doc_make_aa) {
      auto header_sdlang_tag = headerSDLangGet(header_sdlang_src); // sdlang.ast.Tag
      auto header_aa_tuple = headerSDLangToAAmake(header_sdlang_tag, conf_doc_make_aa);
      return header_aa_tuple;
    }
    
  }
}