/++
  read configuration files<BR>
  - read config files<BR>
  meta_config_files.d
+/
module doc_reform.io_in.paths_source;
import std.array,
  std.file,
  std.path,
  std.regex,
  std.stdio,
  std.conv : to;
import
  doc_reform.meta.defaults,
  doc_reform.meta.rgx;
template PodManifest() {
  mixin spineRgxInit;
  static auto rgx = Rgx();
  auto PodManifest(P)(
    P   _pth=""
  ) {
    struct ManifestFile_ {
      string pod_manifest_filename() {
        return "pod.manifest";
      }
      string pod_manifest_path() {
        string _manifest_path;
        if ((isValidPath(_pth) && exists(_pth)!=0 && _pth.isDir)
        && (exists(_pth.chainPath(pod_manifest_filename).array)!=0
        && (_pth.chainPath(pod_manifest_filename).array).isFile)) {
          _manifest_path = _pth;
        } else if (_pth.match(rgx.src_pth_contents)
        && exists(_pth)!=0 && _pth.isFile) {
          _manifest_path = _pth.dirName;
        } else if (_pth.match(rgx.src_pth_pod_sst_or_ssm)
        && exists(_pth)!=0 && (_pth.isFile)) {
          if (auto m = _pth.match(rgx.src_pth_pod_sst_or_ssm)) {
            _manifest_path = m.captures["podpath"];
          }
        } else  {
          writeln("WARNING, issue with manifest_path: ", _pth);
          _manifest_path = null; // _manifest_path = "";
        }
        return _manifest_path;
      }
      string pods_collection_root_path() {
        return (pod_manifest_path.length > 0) ? ((chainPath(pod_manifest_path, "..")).asNormalizedPath).array.to!string : "";
      }
      string pod_manifest_file_with_path() {
        string _k;
        if  (exists(pod_manifest_path.chainPath(pod_manifest_filename).array)!=0) {
          _k = pod_manifest_path.chainPath(pod_manifest_filename).array;
        } else if (exists(pod_manifest_path)!=0) {
          _k = pod_manifest_path;
        }
        if (exists(_k)==0) {
          writeln("ERROR >> Processing Skipped! Manifest not found: ", _k);
          _k = null;
        }
        return _k;
      }
    }
    return ManifestFile_();
  }
}
template PathMatters() {
  mixin spineRgxInit;
  mixin InternalMarkup;
  static auto rgx  = Rgx();
  static auto mkup = InlineMarkup();
  auto PathMatters(O,E)(
    O        _opt_actions,
    E        _env,
    string   _pth,
    string   _fns              = "",
    char[][] _manifest_fn_list = [[]],
  ) {
    auto _manifested = PodManifest!()(_pth);
    struct ManifestMatters_ {
      auto env() {
        auto _env = _env;
        struct Env_ {
          auto pwd() {
            return _env["pwd"];
          }
          auto home() {
            return _env["home"];
          }
        }
        return Env_();
      }
      auto opt() {
        struct Opt_ {
          auto action() {
            return _opt_actions;
          }
        }
        return Opt_();
      }
      bool src_is_pod() {
        return (_manifested.pod_manifest_path.length > 0) ? true : false;
      }
      auto pod() {
        struct Pod_ {
          bool src_is_pod() {
            return (_manifested.pod_manifest_path.length > 0) ? true : false;
          }
          string collection_root() {
            return _manifested.pods_collection_root_path;
          }
          string manifest_filename() {
            return _manifested.pod_manifest_filename;
          }
          string manifest_path() {
            return _manifested.pod_manifest_path;
          }
          string pod_name_with_path() {
            return _manifested.pod_manifest_path.baseName;
          }
          string manifest_file_with_path() {
            return _manifested.pod_manifest_file_with_path;
          }
          string[] config_dr_document_make_dirs() {
            string[] _config_dirs;
            return _config_dirs;
          }
          string[] config_local_site_dirs() {
            string[] _config_dirs;
            return _config_dirs;
          }
          string[] image_dirs() {
            string[] _image_dirs;
            return _image_dirs;
          }
          auto manifest_list_of_filenames() {
            return _manifest_fn_list;
          }
          string[] manifest_list_of_languages() {
            string[] _lngs;
            foreach (filename_; manifest_list_of_filenames) {
              string _k = "en";
              if (auto m = (filename_).match(rgx.language_code_and_filename)) {
                _k = m.captures[1].to!string;
              }
              _lngs ~= _k; // all the languages from the manifest list of filenames with paths
            }
            return _lngs;
          }
        }
        return Pod_();
      }
      auto src() {
        string _fns = _fns; // required here by dmd & not by ldc (for D:2078)
        auto _opt_actions = _opt_actions;
        auto _env = _env;
        struct SRC_ {
          bool is_pod() {
            return (_manifested.pod_manifest_path.length > 0) ? true : false;
          }
          string path_and_fn() {
            return _fns;
          }
          string pod_name_with_path() {
            return (is_pod) ? _manifested.pod_manifest_path : "";
          }
          string pods_collection_root_path() {
            return (is_pod) ? _manifested.pods_collection_root_path : "";
          }
          string pod_name() {
            return pod_name_with_path.baseName;
          }
          string filename() {
            return path_and_fn.baseName;
          }
          string filename_base() {
            return filename.stripExtension;
          }
          string filename_extension() {
            return filename.match(rgx.src_pth_sst_or_ssm).captures["extension"];
          }
          string lng() {
            string _k;
            if (auto m = path_and_fn.match(rgx.language_code_and_filename)) {
              _k = m.captures[1];
            } else {_k = "en"; }
            return _k;
          }
          string doc_uid() {
            string _uid;
            if (is_pod && !(pod_name_with_path.empty)) {
              if (pod_name_with_path.baseName == filename_base) {
                _uid = filename_base ~ "." ~ filename_extension ~ mkup.sep ~ lng;
              } else {
                _uid = pod_name_with_path.baseName ~ mkup.sep ~ filename_base ~ "." ~ filename_extension ~ mkup.sep ~ lng;
              }
            } else {
              _uid = mkup.sep ~ filename_base ~ "." ~ filename_extension ~ mkup.sep ~ lng;
            }
            return _uid;
          }
          string doc_uid_out() {
            string _uid;
            if (is_pod && !(pod_name_with_path.empty)) {
              if (pod_name_with_path.baseName == filename_base) {
                _uid = filename_base ~ "." ~ lng;
              } else {
                _uid = pod_name_with_path.baseName ~ mkup.sep ~ filename_base ~ "." ~ lng;
              }
            } else {
              _uid = "_" ~ filename_base ~ "." ~ lng;
            }
            return _uid;
          }
          string docname_composite_unique_per_src_doc() {
            string _fn;
            if (pod_name_with_path.baseName == filename_base) {
              _fn = filename_base ~ mkup.sep ~ filename_extension ~ mkup.sep ~ lng;
            } else if (!(pod_name_with_path.empty)) {
              _fn = pod_name_with_path.baseName ~ mkup.sep ~ filename_base ~ mkup.sep ~ filename_extension ~ mkup.sep ~ lng;
            } else {
              _fn = "_" ~ mkup.sep ~ filename_base ~ mkup.sep ~ filename_extension ~ mkup.sep ~ lng;
            }
            return _fn;
          }
          string docname_composite_unique_per_src_pod() {
          /+
            z pod name if any + src filename (without lng code)
             filename ~ mkup.sep ~ lng
             * unique per src pod
             used by
             - pod (multilingual collection)
             - sqlite discrete index (multilingual collection)
          +/
            string _fn;
            if (pod_name_with_path.baseName == filename_base) {
              _fn = filename_base ~ mkup.sep ~ filename_extension;
            } else if (!(pod_name_with_path.empty)) {
              _fn = pod_name_with_path.baseName ~ mkup.sep ~ filename_base ~ mkup.sep ~ filename_extension;
            } else {
              _fn = "_" ~ mkup.sep ~ filename_base ~ mkup.sep ~ filename_extension;
            }
            return _fn;
          }
          string language() {
            return lng();
          }
          string file_with_absolute_path() {
            return _env["pwd"].chainPath(path_and_fn).array;
          }
          string absolute_path_to_src() {
            return (_env["pwd"].chainPath(path_and_fn)).dirName.array;
          }
          string path_to_doc_root_path_to_lang_and_filename() {
            return _env["pwd"].chainPath(path_and_fn).array;
          }
          string base_dir() {
            string _dir;
            if (
              auto m = (absolute_path_to_src)
              .match(regex(r"[/](?P<dir>(?:[a-zA-Z0-9._-]+))/pod/" ~ filename.stripExtension))
            ) {
              _dir = ((path_and_fn.chainPath("../../")).asNormalizedPath).array;
              assert(_dir == m.captures["dir"]);
            } else {
              _dir = ((path_and_fn.chainPath("../../../")).asNormalizedPath).array;
              assert(_dir == absolute_path_to_src
                .match(rgx.src_base_parent_dir_name).captures["dir"]);
            }
            if (_opt_actions.debug_do) {
              writeln("--> (base_dir)  ", _dir);
            }
            return _dir;
          }
          string base_parent_dir_path() {
            string _dir;
            if (
              auto m = (absolute_path_to_src)
              .match(regex(r"[/](?P<dir>(?:[a-zA-Z0-9._-]+))/pod/" ~ filename.stripExtension))
            ) {
              _dir = ((path_and_fn.chainPath("../../")).asNormalizedPath).array;
            } else {
              _dir = ((path_and_fn.chainPath("../../../")).asNormalizedPath).array;
            }
            return _dir;
          }
          string base_dir_path() {
            string _dir;
            if (
              auto m = (absolute_path_to_src)
              .match(rgx.src_formalised_file_path_parts)
            ) {
              _dir = ((m.captures["pth"]).asNormalizedPath).array;
            } else if (
             auto m = (absolute_path_to_src)
             .match(regex(r"[/](?P<dir>(?:[a-zA-Z0-9._-]+))/pod/" ~ filename.stripExtension))
            ) {
              _dir = ((path_and_fn.chainPath("../")).asNormalizedPath).array;
            } else {
              _dir = ((path_and_fn.chainPath("../../")).asNormalizedPath).array;
            }
            if (_opt_actions.debug_do) {
              writeln("--> (base_dir_path) ", _dir);
            }
            return _dir;
          }
          string media_dir_path() {
            string _dir = ((base_dir_path.chainPath("media")).asNormalizedPath).array;
            return _dir;
          }
          string image_dir_path() {
            string _paths;
            string[] _possible_img_pths = [ "./image", "../image", "../../image" ];
            string _img_pth_found = "";
            if (is_pod) {
              _img_pth_found = ((file_with_absolute_path.dirName ~ "/../../image").asNormalizedPath).array;
            } else {
              string _img_pth(string _possible_img_pth) {
                return ((file_with_absolute_path.dirName ~ "/" ~ _possible_img_pth).asNormalizedPath).array;
              }
              foreach(_possible_img_pth; _possible_img_pths) {
                if (exists(_img_pth(_possible_img_pth))) {
                  _img_pth_found = _img_pth(_possible_img_pth);
                  break;
                } else {
                  _paths ~= " " ~ _img_pth(_possible_img_pth);
                }
              }
            }
            if (_img_pth_found.empty) {
              writeln("WARNING not image path found, searched: ", _paths);
            }
            return _img_pth_found;
          }
          auto conf_dir_path() {
            return ((base_dir_path.chainPath("conf")).asNormalizedPath).array;
          }
          auto base_parent_dir() {
            string _dir;
            if (
              auto m = (absolute_path_to_src)
              .match(regex(r"[/](?P<dir>(?:[a-zA-Z0-9._-]+))/pod/" ~ filename.stripExtension))
            ) {
              _dir = m.captures["dir"];
            } else {
              _dir = (absolute_path_to_src).match(rgx.src_base_parent_dir_name).captures["dir"];
            }
            if (_opt_actions.debug_do) {
              writeln("--> (base_parent_dir) ", _dir);
            }
            return _dir;
          }
          string[] config_dirs() {
            string[] _config_dirs;
            if (is_pod) {
            } else {}
            return _config_dirs;
          }
          string[] image_dirs() {
            string[] _image_dirs;
            if (is_pod) {
            } else {}
            return _image_dirs;
          }
        }
        return SRC_();
      }
      auto output() {
        /+
          - command line if output path set
          - config file if found and set set
            - search for and if exists read config
              - default paths to config related to:
                - source markup path;
                - current dir;
                - home dir
              - get output path if set
          - (program) default within current directory?
        +/
        auto _env = _env;
        struct Out_ {
          auto path() {
            auto _output_path = _env["pwd"];
            if ((_opt_actions.output_dir_set.length > 0)
              && isValidPath(_opt_actions.output_dir_set)
            ) {
              _output_path = ((_opt_actions.output_dir_set).asNormalizedPath).array;
              if (!exists(_output_path)) {
                try {
                  _output_path.mkdirRecurse;
                // } catch (ErrnoException ex) {
                } catch (Exception ex) {
                  // Handle error
                }
              }
              assert(_output_path.isDir,
                "not a directory: " ~ _output_path);
              // TODO always test that is a directory and it is writable
            }
            return _output_path;
          }
        }
        return Out_();
      }
    }
    return ManifestMatters_();
  }
}
template ConfigFilePaths() {
  mixin spineRgxInit;
  static auto rgx = Rgx();
  auto ConfigFilePaths(M,E)(
    M      _manifested,
    E      _env,
    string _cli_config_path_set = ""
  ) {
    struct ConfFilePaths {
      string config_filename_document() {
        return "dr_document_make";
      }
      string config_filename_site() {
        return "config_local_site";
      }
      auto possible_config_path_locations() {
        struct _ConfFilePaths {
          string[] dr_document_make() {
            /+ FIX clean up conf paths ↓ +/
            /+ config local site (file system only, not in pod) +/
            /+ return paths +/
            string[] _possible_config_path_locations;
            if (_cli_config_path_set.empty) {
              if (_manifested.src.is_pod) {
                /+ config document in pod +/
                string _dr_doc_conf_pod;
                string _dr_doc_conf_pod_text;
                _dr_doc_conf_pod = asNormalizedPath(chainPath(
                  to!string(_env["pwd"]),
                  _manifested.pod.manifest_path ~ "/conf"
                )).array;
                _dr_doc_conf_pod_text = asNormalizedPath(chainPath(
                  to!string(_env["pwd"]),
                  _manifested.pod.manifest_path ~ "/media/text/" ~ _manifested.src.lng ~ "/conf"
                )).array;
                /+ return paths +/
                _possible_config_path_locations = [
                  _dr_doc_conf_pod_text,
                  _dr_doc_conf_pod,
                ];
              } else {
                /+ config document (& or local site) on filesystem +/
                string _dr_doc_conf_pwd   = ((chainPath(to!string(_env["pwd"]), "dr_doc/conf")).asNormalizedPath).array; // think about
                string _dr_doc_conf_pwd_a = ((chainPath(to!string(_env["pwd"]), "conf")).asNormalizedPath).array;
                string _dr_doc_conf_pwd_b = ((chainPath(to!string(_env["pwd"]), "../conf")).asNormalizedPath).array;
                string _dr_doc_conf_pwd_c = ((chainPath(to!string(_env["pwd"]), "../../conf")).asNormalizedPath).array;
                string _dr_doc_conf_pwd_d = ((chainPath(to!string(_env["pwd"]), "../../../conf")).asNormalizedPath).array;
                /+ return paths +/
                _possible_config_path_locations = [
                  _dr_doc_conf_pwd,
                  _dr_doc_conf_pwd_a,
                  _dr_doc_conf_pwd_b,
                  _dr_doc_conf_pwd_c,
                  _dr_doc_conf_pwd_d,
                ];
              }
            } else {
              _possible_config_path_locations = [
                _cli_config_path_set
              ];
            }
            /+ FIX clean up conf paths ↑
            (compare pwd to doc path location, and build config path)
            +/
            return _possible_config_path_locations;
          }
          string[] config_local_site() {
            /+ FIX clean up conf paths ↓ +/
            /+ config local site (file system only, not in pod) +/
            string[] _possible_config_path_locations;
            if (_cli_config_path_set.empty) {
              string _dot_pwd        = ((chainPath(to!string(_env["pwd"]), ".dr")).asNormalizedPath).array;
              string _underscore_pwd = ((chainPath(to!string(_env["pwd"]), "_dr")).asNormalizedPath).array;
              string _dot_home       = ((chainPath(to!string(_env["home"]), ".dr")).asNormalizedPath).array;
              /+ return paths +/
              if (_manifested.src.is_pod) {
                string _collection_root_a = ((chainPath(to!string(_manifested.pod.collection_root.to!string), ".dr")).asNormalizedPath).array;
                string _collection_root_b = ((chainPath(to!string(_manifested.pod.collection_root.to!string), "_dr")).asNormalizedPath).array;
                _possible_config_path_locations = [
                  _dot_pwd,
                  _underscore_pwd,
                  _dot_home,
                  "/etc/dr",
                  _collection_root_a, // set priority higher?
                  _collection_root_b  // set priority higher?
                ];
              } else {
                /+ config document (& or local site) on filesystem +/
                string _dr_doc_conf_pwd   = ((chainPath(to!string(_env["pwd"]), "dr_doc/conf")).asNormalizedPath).array;
                string _dr_doc_conf_pwd_a = ((chainPath(to!string(_env["pwd"]), "conf")).asNormalizedPath).array;
                string _dr_doc_conf_pwd_b = ((chainPath(to!string(_env["pwd"]), "../conf")).asNormalizedPath).array;
                string _dr_doc_conf_pwd_c = ((chainPath(to!string(_env["pwd"]), "../../conf")).asNormalizedPath).array;
                string _dr_doc_conf_pwd_d = ((chainPath(to!string(_env["pwd"]), "../../../conf")).asNormalizedPath).array;
                _possible_config_path_locations = [
                  _dr_doc_conf_pwd,
                  _dr_doc_conf_pwd_a,
                  _dr_doc_conf_pwd_b,
                  _dr_doc_conf_pwd_c,
                  _dr_doc_conf_pwd_d,
                  _dot_pwd,
                  _underscore_pwd,
                  _dot_home,
                  "/etc/dr"
                ];
              }
            } else {
              _possible_config_path_locations = [
                _cli_config_path_set
              ];
            }
            /+ FIX clean up conf paths ↑
            (compare pwd to doc path location, and build config path)
            +/
            return _possible_config_path_locations;
          }
        }
        return _ConfFilePaths();
      }
    }
    return ConfFilePaths();
  }
}
template spinePathsSRC() {
  mixin spineRgxInit;
  static auto rgx = Rgx();
  auto spinePathsSRC(D,Fn)(
    D   _pwd,
    Fn  _fn_src_and_path,
  ) {
    struct drSrcPaths {
      auto pwd() {
        return _pwd;
      }
      string language() {
        // use command line info as well?
        string _k;
        if (auto m = _fn_src_and_path.match(rgx.language_code_and_filename)) {
          _k = m.captures[1];
        } else { /+ unknown until doc_meta read, (could provide & use command line info?) +/
          _k = "xx"; // original default was "en" but is not known
        }
        return _k;
      }
      string doc_root() {
        return "dr_doc";
      }
      auto media_root() {
        return ((doc_root.chainPath("media")).asNormalizedPath).array;
      }
      auto conf_root() {
        return ((doc_root.chainPath("conf")).asNormalizedPath).array;
      }
      auto text_root() {
        return ((media_root.chainPath("text")).asNormalizedPath).array;
      }
      auto image_root() {
        return ((media_root.chainPath("image")).asNormalizedPath).array;
      }
      auto doc_src_fn_with_path_for_text_root_and_lng() {
        return ((text_root.chainPath(language)).asNormalizedPath).array;
      }
      auto doc_src_fn() {
        return ((_fn_src_and_path.baseName).asNormalizedPath).array;
      }
      auto doc_src_with_path() {
        return ((pwd.chainPath(_fn_src_and_path)).asNormalizedPath).array;
      }
    }
    return drSrcPaths();
  }
}


template spinePathsPods() {
  mixin spineRgxInit;
  static auto rgx = Rgx();
  string _suffix = ".zip";
  auto spinePathsPods(M)(M doc_matters) {
    string _base_dir_pod = (doc_matters.output_path.length > 0)
    ? doc_matters.output_path ~ "/pod"
    : "/pod";
    string _base_dir_doc = "dr_doc";
    struct _PodPaths {
      string base_filename_(string fn_src) {
        auto pth = fn_src.baseName.stripExtension;
        return pth;
      }
      string pod_dir_() {
        auto pth = _base_dir_pod;
        return pth;
      }
      string dr_doc_dir_() {
        auto pth = _base_dir_doc;
        return pth;
      }
      string pod_filename_(string fn_src) {
        string pth = _base_dir_pod.chainPath(base_filename_(fn_src) ~ _suffix).array;
        return pth;
      }
      string base_filesystem_(string fn_src) {
        string pth = _base_dir_pod.chainPath(base_filename_(fn_src)).array;
        assert(pth == _base_dir_pod ~ "/"  ~ base_filename_(fn_src),
          pth ~ " == "  ~ _base_dir_pod ~ "/" ~ base_filename_(fn_src) ~ "?");
        return pth;
      }
      string output_pod_manifest_file(string fn_src) {
        string pth = base_filesystem_(fn_src).chainPath("pod.manifest").array;
        return pth;
      }
      string base_pod_(string fn_src) {
        string pth = _base_dir_pod.chainPath(base_filename_(fn_src)).array; // change this
        return pth;
      }
      auto base_filename(string fn_src) {
        auto pth_1_ = base_filename_(fn_src);
        auto pth_2_ = base_filename_(fn_src);
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            return pth_2_;
          }
        }
        return _pods();
      }
      auto pod_filename(string fn_src) {
        auto pth_1_ = pod_filename_(fn_src);
        auto pth_2_ = pod_filename_(fn_src);
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            return pth_2_;
          }
        }
        return _pods();
      }
      auto base(string fn_src) {
        auto pth_1_ = "";
        auto pth_2_ = base_filesystem_(fn_src);
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            return pth_2_;
          }
        }
        return _pods();
      }
      auto pod_root(string fn_src) {
        auto pth_1_ = "pod";
        auto pth_2_ = ((base(fn_src).filesystem_open_zpod.chainPath("")).asNormalizedPath).array; // "dr_doc"
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            return pth_2_;
          }
        }
        return _pods();
      }
      auto conf_root(string fn_src) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = "conf";
        auto pth_2_ = ((pod_root(fn_src).filesystem_open_zpod.chainPath("conf")).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto css(string fn_src) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = ((conf_root(fn_src).zpod.chainPath("css")).asNormalizedPath).array;
        auto pth_2_ = ((conf_root(fn_src).filesystem_open_zpod.chainPath("css")).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto pod_manifest(string fn_src) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = ((pod_root(fn_src).zpod.chainPath("pod.manifest")).asNormalizedPath).array;
        auto pth_2_ = ((pod_root(fn_src).filesystem_open_zpod.chainPath("pod.manifest")).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto media_root(string fn_src) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = ((pod_root(fn_src).zpod.chainPath("media")).asNormalizedPath).array;
        auto pth_2_ = ((pod_root(fn_src).filesystem_open_zpod.chainPath("media")).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto text_root(string fn_src) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = ((media_root(fn_src).zpod.chainPath("text")).asNormalizedPath).array;
        auto pth_2_ = ((media_root(fn_src).filesystem_open_zpod.chainPath("text")).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto doc(string fn_src) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = text_root(fn_src).zpod;
        auto pth_2_ = text_root(fn_src).filesystem_open_zpod;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto doc_lng(string fn_src, string lng) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = ((text_root(fn_src).zpod.chainPath(lng)).asNormalizedPath).array;
        auto pth_2_ = ((text_root(fn_src).filesystem_open_zpod.chainPath(lng)).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto image_root(string fn_src) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = ((media_root(fn_src).zpod.chainPath("image")).asNormalizedPath).array;
        auto pth_2_ = ((media_root(fn_src).filesystem_open_zpod.chainPath("image")).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto fn_pod_filelist(string fn_src) {
        auto pod_root_ = pod_root(fn_src);
        auto _manifested = PodManifest!()(fn_src).pod_manifest_filename;
        auto pth_1_ = _manifested;
        auto pth_2_ = ((pod_root(fn_src).filesystem_open_zpod.chainPath(_manifested)).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto fn_doc(string fn_src, string lng) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = ((doc_lng(fn_src, lng).zpod.chainPath(fn_src.baseName)).asNormalizedPath).array;
        auto pth_2_ = ((doc_lng(fn_src, lng).filesystem_open_zpod.chainPath(fn_src.baseName)).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
      auto fn_doc_insert(string fn_src, string fn_insert, string lng) {
        auto pod_root_ = pod_root(fn_src);
        auto pth_1_ = ((doc_lng(fn_src, lng).zpod.chainPath(fn_insert.baseName)).asNormalizedPath).array;
        auto pth_2_ = ((doc_lng(fn_src, lng).filesystem_open_zpod.chainPath(fn_insert.baseName)).asNormalizedPath).array;
        struct _pods {
          auto zpod() {
            return pth_1_;
          }
          auto filesystem_open_zpod() {
            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_);
            return pth_2_;
          }
        }
        return _pods();
      }
    }
    return _PodPaths();
  }
}