copy_from=".";
expr_target = r"jl_[A-Za-z0-9]{6}";
expr_removebackslash = r"^(\\|/){1,2}";

notice = Markdown.parse("""
1. Please apply the following first:
```
using Weave, GeneralTools
```

2. You can alternatively specify the weave option in the front matter. For example, add the following to the front matter (header) of the your julia-markdown file:
```
weave_options: 
  fig_path: ./
  hugo:
    out_path: ./_index.md
  md2pdf:
    out_path : ../pdf
  md2html:
    out_path : ./_index.html
```
Notice that in this way the path is relative to the path of julia markdown, not the current directory. That is, for that in the front matter we have `out_path: ./_index.md` and doing `weave("$copy_from/your_file.md")`, the result is the same as `weave(...; out_path="$copy_from/_index.md")`

""");


default_outname = "_index.md";
"""
`cp2content(dst::AbstractString)` copy the generated hugo markdown file to your site's `content`. `cp2content` looks in `dst` for `$default_outname` or `index.md` and images.
# Example 
```
lazyhugo();
cp2content("D:/GoogleDrive/Sites/learning-notes/content/en/my-project/MagTIP");
```

# keyword arguments
- `copy_from="$copy_from"` is defined by default; that is, the markdown file generated by `lazyhugo()` and all images in the directory `copy_from` will be copied and send to `dst`.
- `rename_to` allows you to rename the output markdown file. For example, you'd like to `rename_to="my_project.md"`. Default is `rename_to=false`.


# Notice
$notice

"""
function cp2content(dst::AbstractString; force=true, copy_from=copy_from, rename_to=false)

    allfiles = readdir(copy_from, join=true);

    bnames = splitext.(allfiles); # base names
    isfig = map(x -> occursin(r"\.(png|jpe?g|svg|eps|gif|apng)",x[end]), bnames);
    isindex = occursin.(r"_?index\.md", basename.(allfiles));
    
    figures = allfiles[isfig];
    theindex = allfiles[isindex];
    
    if length(theindex) != 1 
        openit(joinpath(pwd(),copy_from));
        error("No or more than one `index.md` file(s). `weave` first and check the opened folder!");
    end
    

    
    src = [figures;theindex];	# make sure the "index.md" be the last element of src
    dsts = joinpath.(dst,basename.(src)); # hence "index.md" be the last element of dsts
    
    if isa(rename_to, String)
        dsts[end] = renamefile(dsts[end], rename_to);
    end
    
    cp.(src, dsts; force=force);
       
    println("Files copied to $dst except:");
    println.(allfiles[.!(isfig .| isindex)]);
end


default_outpath = "_index.md";
default_figpath = "";
"""
`lazyhugo([filename]; out_path="$default_outpath")` is equivalent to `weave("\$filename"; doctype="hugo", out_path="$default_outpath", fig_path="$default_figpath")`. 

Simply `lazyhugo()` automatically search for a julia markdown file (`.jmd`) of any name first, then the markdown file not named as "_index.md" or "index.md".
Once a unique juliamarkdown file is found, it quit searching immediately; but if multiple or no (julia) markdown files were found, an error will be raised. 
    
If `filename` is suffixed with `.md` (a markdown file instead of julia markdown), then weave option `informat="markdown"` will be added. If the first argument is a folder name, then `lazyhugo` search julia markdown then markdown files inside the folder.

`lazyhugo` also reformat `{{< figure src="/using_gadfly_14_1.png"  >}}`. The `/using_gadfly_14_1.png` is captured with the first slash being deleted, leading to `![](using_gadfly_14_1.png)`

# Notice
$notice

"""
function lazyhugo(; out_path=default_outpath)
  opt = [];
  allfiles = readdir();
  id = occursin.(r"\.jmd",allfiles); # check if there is .jmd file
  if all(.!id) # if there is not any .jmd exist, then find something with extension .md.
      id = occursin.(r"(?<!index)\.md",allfiles);
  end
  
  filenames = allfiles[id];
  if length(filenames) != 1
      error("No or multiple markdown files exists. Please explicitily specify the target file you want to weave. For example, `lazyhugo(Doc.md)` or `lazyhugo(Doc.jmd)`. Noted that your markdown file to be converted cannot be named as `index.md`.");
  end
  
  filename = filenames[1];
  println("`$filename` is going to be weaved:");
  _lazyhugo(filename, out_path, opt);
end

function lazyhugo(filename::AbstractString; out_path=default_outpath)
  opt = [];
  if !isfile(filename) # which means the first arg is expected to be a folder containing `.jmd` or `_index.md`
      currentdir = pwd();
      cd(filename);

      try
          lazyhugo(; out_path=out_path);
      catch e
          cd(currentdir);
          throw(e);
      end
      cd(currentdir);
      return
  end

  if splitext(filename)[end] == ".md"
      opt = [:informat => "markdown"]; 
  end
  _lazyhugo(filename, out_path, opt);
end

function _lazyhugo(filename::AbstractString, out_path, opt)
  weave("$filename"; doctype="hugo", out_path=out_path, fig_path=default_figpath, opt...);
  # Reformat figure referencing and remove extra first slash/backslash if there is any, because the slash/backslash makes referencing fail.
  txt = readlines(out_path);
  lines2replace = occursin.(r"(?<=figure src=)", txt);
  if !any(lines2replace)
    return
  end
  matches = match.(r"(?<=\").*(?=\")",txt[lines2replace]);
  newfigref = String[];
  for mt in matches
    str0 = mt.match;
    str1 = replace(str0, expr_removebackslash => "");
    newref = "![]($str1)"
    push!(newfigref, newref);
  end


  txt[lines2replace] .= newfigref;
  
  open(out_path, "w") do io
    for line in txt
      println(io, line);
    end
  end
end


"""
`getdoc(filepath::String; first_head=0)`
read the function descriptions and return a `Markdown.parse`d object.
Now it supports matlab's `.m` function only. 
TODO: add julia support.

# Example (matlab)
- `y = getdoc("..\\..\\src\\statind.m")` get all the comments (starts with `% ` eachline) `before function statind(...)`
- `y = getdoc("..\\..\\src\\statind.m", first_head=3)` get all the comments before function section and rearrange all the heading levels based on forcing the first heading level to be 3. That is, take the first heading to be `#` for example, `#` becomes `###` and `##` becomes `####`
"""
function getdoc(filepath::String; first_head=0)
  
  
  s = open(filepath) do file
    readlines(file);
    end
  if splitext(filepath)[end] == ".m" # if it is the matlab file
    doc = _getrawcomment(s);
    x = join(lang_matlab(doc,first_head = first_head));
    y = Markdown.parse(x); # or @eval @md_str $x is the same.
  else
    y = Markdown.parse("<unsupported language>");
  end
  
  return y
end

function _getrawcomment(s)
  funbegin = findfirst(occursin.(r"^(function|classdef)\s",s));
  # find the line where function begin
  if funbegin == 1
    return "No documentation."
  end
  
  if isnothing(funbegin)
    docend = length(s);
  else
    docend = funbegin - 1;
  end
  
  doc = s[1:docend];   
end

function lang_matlab(doc; first_head=0)
  # for Weave.jl, both default or pandoc2html output, mulitiple empty lines == one and results in a linebreak, and linebreak (but no empty line in between) is ignored. So I add linebreaks very generously here.
  br = "\n"; # linebreak
  # delete "%" in the beginning of the line.
  doc2 = replace.(doc, r"^%+\s?" => "");

  if first_head != 0 # reformat markdown head levels
    lenhashtags0 = match(r"^#+",doc2[1]).match |> length;
    adjust_diff = first_head - lenhashtags0;
    
    ishead = occursin.(r"^#+",doc2[1:end]);
    targetid = findall(ishead);
    for i in targetid
      lenhashtags_i = match.(r"^#+",doc2[i]).match |> length;
      new_head = "#"^(lenhashtags_i+adjust_diff);
      doc2[i] = replace(doc2[i], r"^#+" => new_head);
    end
  end
  
  for (i,val) in enumerate(doc2)
    doc2[i] = val*br; # add linebreak at the end of every line.
  end
  
  # codefence = findall(occursin.(r"^(```)",doc2));
  # codestart = codefence[1:2:end];
  # codeend = codefence[2:2:end];
  
  # numinserted = 0;

  # for id in codefence
  # 	id = id + numinserted;
  # 	# if iseven(numinserted)
  # 	# 	insertat = id; # insert before
  # 	# else
  # 	# 	insertat = id+1;  # insert after
  # 	# end
  # 	insert!(doc2, id, br); # add linebreak before
  # 	insert!(doc2, id+2, br); # add linebreak after
  # 	numinserted = numinserted + 2;
  # end
  return doc2
end


"""
`defolder(dir::AbstractString)`
Delete all folders left everytime we use the `weave(...;out_path=dir)`. The target folders are captured with regular expression pattern `r"jl_[A-Za-z0-9]{6}"`.

`defolder()` search targets at current directory.

"""
function defolder(dir::AbstractString;force=false)
  _defolder(dir, force);
end

function defolder(;force=false)
  dir = pwd();
  _defolder(dir, force);
end

function _defolder(dir, force::Bool)
  
  dir = abspath(dir); # reformat the path to prevent something like "dir/to/target\\jl_x3as5e"
  flist = readdir(dir, join=true);
  dirtrue = isdir.(flist);
  fmtmatched = .!isnothing.(match.(expr_target,flist));
  targets = flist[dirtrue .& fmtmatched];
  if isempty(targets)
      println("No target folder found. Do nothing.");
      return nothing
  end  
    
  try
    rm.(targets; recursive=force);
  catch e
    str = sprint(showerror, e);
    openit(dir);
    @warn ("Some of the target folders are not empty [$str]. Set `force=true` to delete all of them without prompt.");
    println("Delete them anyway? (y/n)");
    if readline(stdin) == "y"
      _defolder(dir, true);
    end
  end
   

end