/+
  ao_read_source_files.d
  - open markup files
  - if master file scan for addional files to import/insert
+/
// module ao_read_source_files;
template SiSUmarkupRaw() {
  private import
    std.exception,
    std.regex,
    std.stdio,
    std.utf,
    std.conv : to;
  private import
    ao_rgx;       // ao_defaults.d
  mixin RgxInit;
  auto rgx = Rgx();
  struct MarkupRaw {
    auto sourceContent(in string fn_src) {
      auto raw = MarkupRawUnit();
      auto t =
        raw.markupSourceHeaderContentRawLineTupleArray(fn_src, rgx.src_pth);
      auto header_raw = t[0];
      auto sourcefile_content = t[1];
      if (match(fn_src, rgx.src_fn_master)) {
        auto ins = Inserts();
        sourcefile_content =
          ins.scan_master_src_for_insert_files_and_import_content(sourcefile_content, fn_src);
        // auto ins = SiSUdocInserts.Inserts();
      }
      t = tuple(
        header_raw,
        sourcefile_content
      );
      return t;
    }
  }
  private
  struct MarkupRawUnit {
    private import std.file;
    // enum State { off, on }
    final private string readInMarkupSource(in string fn_src) {
      enforce(
        exists(fn_src)!=0,
        "file not found"
      );
      string source_txt_str;
      try {
        if (exists(fn_src)) {
          source_txt_str = readText(fn_src);
        }
      }
      catch (ErrnoException ex) {
      //// Handle errors
      // switch(ex.errno) {
      // case EPERM:
      // case EACCES:
      //   // Permission denied
      //   break;
      // case ENOENT:
      //   // File does not exist
      //   break;
      // default:
      //   // Handle other errors
      //   break;
      // }
      }
      catch (UTFException ex) {
        // Handle validation errors
      }
      catch (FileException ex) {
        // Handle errors
      }
      std.utf.validate(source_txt_str);
      return source_txt_str;
    }
    final private char[][] header0Content1(in string src_text) {
      /+ split string on first match of "^:?A~\s" into [header, content] tuple +/
      char[][] header_and_content =
        split(cast(char[]) src_text, rgx.heading_a);
      return header_and_content;
    }
    final private char[][] markupSourceLineArray(in char[] src_text) {
      char[][] source_line_arr =
        split(cast(char[]) src_text, rgx.line_delimiter);
      return source_line_arr;
    }
    auto markupSourceHeaderContentRawLineTupleArray(in string fn_src, Regex!(char) rgx_file ) {
      enforce(
        match(fn_src, rgx_file),
        "not a sisu markup filename"
      );
      auto source_txt_str = readInMarkupSource(fn_src);
      auto hc = header0Content1(source_txt_str);
      auto header = hc[0];
      char[] la;
      la ~= "A~ ";
      char[] source_txt = la ~ hc[1];
      auto source_line_arr = markupSourceLineArray(source_txt);
      auto t = tuple(
        header,
        source_line_arr
      );
      return t;
    }
    final char[][] markupSourceContentRawLineArray(in string fn_src, Regex!(char) rgx_file ) {
      enforce(
        match(fn_src, rgx_file),
        "not a sisu markup filename"
      );
      auto source_txt_str = readInMarkupSource(fn_src);
      auto source_line_arr = markupSourceLineArray(source_txt_str);
      return source_line_arr;
    }
  }
  struct Inserts {
    private import ao_defaults;    // ao_defaults.d
    private import ao_ansi_colors; // ao_ansi_colors.d
    auto scan_subdoc_source(
      char[][] markup_sourcefile_insert_content,
      string fn_src
    ) {
      mixin SiSUrgxInitFlags;
      char[][] contents_insert;
      auto type1 = flags_type_init;
      auto fn_pth_full = match(fn_src, rgx.src_pth);
      auto markup_src_file_path = fn_pth_full.captures[1];
      foreach (line; markup_sourcefile_insert_content) {
        if (type1["curly_code"] == 1) {
          type1["header_make"] = 0;
          type1["header_meta"] = 0;
          if (matchFirst(line, rgx.block_curly_code_close)) {
            type1["curly_code"] = 0;
          }
          contents_insert ~= line;
        } else if (matchFirst(line, rgx.block_curly_code_open)) {
          type1["curly_code"] = 1;
          type1["header_make"] = 0;
          type1["header_meta"] = 0;
          contents_insert ~= line;
        } else if (type1["tic_code"] == 1) {
          type1["header_make"] = 0;
          type1["header_meta"] = 0;
          if (matchFirst(line, rgx.block_tic_close)) {
            type1["tic_code"] = 0;
          }
          contents_insert ~= line;
        } else if (matchFirst(line, rgx.block_tic_code_open)) {
          type1["tic_code"] = 1;
          type1["header_make"] = 0;
          type1["header_meta"] = 0;
          contents_insert ~= line;
        } else if (
          (type1["header_make"] == 1)
          && matchFirst(line, rgx.native_header_sub)
        ) {
            type1["header_make"] = 1;
            type1["header_meta"] = 0;
            // cont_dynamic_array ~= "% " ~ line;
        } else if (
          (type1["header_meta"] == 1)
          && matchFirst(line, rgx.native_header_sub)
        ) {
            type1["header_meta"] = 1;
            type1["header_make"] = 0;
            // cont_dynamic_array ~= "% " ~ line;
        } else if (auto m = match(line, rgx.insert_src_fn_ssi_or_sst)) {
          type1["header_make"] = 0;
          type1["header_meta"] = 0;
          auto insert_fn = m.captures[2];
          auto insert_sub_pth = m.captures[1];
          auto fn_src_insert =
            to!string(markup_src_file_path ~ insert_sub_pth ~ insert_fn);
          auto raw = MarkupRawUnit();
          auto markup_sourcesubfile_insert_content =
            raw.markupSourceContentRawLineArray(fn_src_insert, rgx.src_fn_find_inserts);
          debug(insert) {                              // insert file
            tell_l("red", line);
            tell_l("red", fn_src_insert);
            tell_l("fuchsia", "ERROR");
            writeln(
              "  length contents insert array: ",
              markup_sourcesubfile_insert_content.length
            );
          }
          auto ins = Inserts();
          /+
            1. load file,
            2. read lines;
            3. scan lines,
            4. if filename insert, and insert filename
            5.   repeat 1
            6. else
            7.   add line to new array;
          +/
        } else {
          type1["header_make"] = 0;
          type1["header_meta"] = 0;
          contents_insert ~= line;
        }
      } // end src subdoc (inserts) loop
      return contents_insert;
    }
    auto scan_master_src_for_insert_files_and_import_content(
      char[][] sourcefile_content,
      string fn_src
    ) {
      mixin SiSUrgxInitFlags;
      char[][] contents;
      auto type = flags_type_init;
      auto fn_pth_full = match(fn_src, rgx.src_pth);
      auto markup_src_file_path = fn_pth_full.captures[1];
      foreach (line; sourcefile_content) {
        if (type["curly_code"] == 1) {
          if (matchFirst(line, rgx.block_curly_code_close)) {
            type["curly_code"] = 0;
          }
          contents ~= line;
        } else if (matchFirst(line, rgx.block_curly_code_open)) {
          type["curly_code"] = 1;
          contents ~= line;
        } else if (type["tic_code"] == 1) {
          if (matchFirst(line, rgx.block_tic_close)) {
            type["tic_code"] = 0;
          }
          contents ~= line;
        } else if (matchFirst(line, rgx.block_tic_code_open)) {
          type["tic_code"] = 1;
          contents ~= line;
        } else if (auto m = match(line, rgx.insert_src_fn_ssi_or_sst)) {
          auto insert_fn = m.captures[2];
          auto insert_sub_pth = m.captures[1];
          auto fn_src_insert =
            to!string(markup_src_file_path ~ insert_sub_pth ~ insert_fn);
          auto raw = MarkupRawUnit();
          /+ TODO +/
          if (auto ma = match(line, rgx.src_fn_text)) {
            /+ .sst when inserted, not used: headers and heading level ^:?A~ so remove +/
            writeln(__LINE__); writeln(ma);
          // auto t =
          //   raw.markupSourceHeaderContentRawLineTupleArray(fn_src, rgx.src_pth);
          }
          auto markup_sourcefile_insert_content =
            raw.markupSourceContentRawLineArray(fn_src_insert, rgx.src_fn_find_inserts);
          debug(insert) {                              // insert file
            tell_l("red", line);
            tell_l("red", fn_src_insert);
            writeln(
              "  length contents insert array: ",
              markup_sourcefile_insert_content.length
            );
          }
          auto ins = Inserts();
          auto contents_insert = ins.scan_subdoc_source(
            markup_sourcefile_insert_content,
            to!string(fn_src_insert)
          );
          contents ~= contents_insert;
          /+
            1. load file,
            2. read lines;
            3. scan lines,
            4. if filename insert, and insert filename
            5.   repeat 1
            6. else
            7.   add line to new array;
          +/
        } else {
          contents ~= line;
        }
      } // end src doc loop
      debug(insert) {                              // insert file
        writeln(__LINE__);
        writeln(contents.length);
      }
      return contents;
    }
  }
}