/++
  sdlang headers<BR>
  extract sdlang header return sdlang
+/
module sdp.ao.conf_make_meta_sdlang;
template SiSUheaderExtractSDLang() {
  import
    std.exception,
    std.regex,
    std.stdio,
    std.string,
    std.traits,
    std.typecons,
    std.utf,
    std.conv : to;
  import
    sdp.ao.defaults,
    sdp.ao.rgx;
  struct HeaderExtractSDL {
    mixin SiSUregisters;
    mixin SiSUrgxInit;
    auto rgx = Rgx();
    private auto sdlangToAAmake(C,Tag)(C conf, Tag conf_sdlang) {
      debug(asserts){
        static assert(is(typeof(conf) == string[string][string]));
      }
      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)(Tag conf_sdlang) {
      auto conf = sdlangToAAmake(conf_aa, conf_sdlang);
      return conf;
    }
    private auto documentMakeSDLangToAAmake(Tag)(Tag document_make_sdlang) {
      auto dochead_make = sdlangToAAmake(make_aa, document_make_sdlang);
      return dochead_make;
    }
    final private auto headerMakeSDLang(Hs)(Hs src_header) {
      debug(asserts){
        static assert(is(typeof(src_header) == string));
      }
      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(Hs)(Hs src_header) {
      debug(asserts){
        static assert(is(typeof(src_header) == char[]));
      }
      char[][] source_header_arr =
        (cast(char[]) src_header).split(rgx.newline_eol_delimiter);
      char[] header_clean;
      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,Ma)(Tag header_sdlang, Ma dochead_make) {
      debug(asserts){
        static assert(is(typeof(dochead_make) == string[string][string]));
      }
      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]);
      }
      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 = dochead_meta["creator"]["author"].split(rgx.arr_delimiter);
      foreach (author_raw; authors_raw_arr) {
        authors_arr ~= author_raw.replace(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(Hs,Ma)(Hs header_sdlang_src, Ma conf_doc_make_aa) {
      debug(asserts){
        static assert(is(typeof(header_sdlang_src) == char[]));
        static assert(is(typeof(conf_doc_make_aa) == string[string][string]));
      }
      auto header_sdlang_tag = headerSDLangGet(header_sdlang_src);
      auto header_aa_tuple = headerSDLangToAAmake(header_sdlang_tag, conf_doc_make_aa);
      return header_aa_tuple;
    }
  }
}