### A Nbdev script file ###
### Autogenerated file. Don't modify. ###

module Export
#export
import Pluto: Notebook, Cell, load_notebook_nobackup

#export
function processMdChunk(mdChunk::String)
	chopMdMarker(mdChunk)
end

#export
begin
"""
> struct Nucleus--> This is the lowest entity of a code notebook. This type represents the code cell in a Pluto notebook.
> * Fields:
>   * code--> String which makes up a code cell
"""
Base.@kwdef mutable struct Nucleus
	code::String=""
	end

"""
> Nucleus(code)-->Getter for accessing the constructer of the Nucleus type
"""
Nucleus(code) = Nucleus(code = code)
end

#export
begin
"""
> struct Nb--> a notebook having nuclei made up of code cells only.
> * Fields:
>   * nuclei--> Array of Nucleus type
>   * name--> name of notebook
"""
mutable struct Nb
	nuclei::Array{Nucleus,1}
	name::AbstractString
end

"""
> nuclei(nuclei::Array)--> Helper to collect an array of Nucleus.	
"""
nuclei(nuclei::Array) = nuclei

"""
> nuclei(nuclei::Array)--> Helper to collect an name of a notebook.
"""
name(name::AbstractString) = name
end

#export
begin
"""
Headers that would appear in a code file
"""
const _header = "### A Nbdev script file ###"
const _sub_header = "### Autogenerated file. Don't modify. ###"
end

#export
"""
This had to be done because having the cell iddelimeter as a constant gives an error during parsing the notebook
"""
cell_id_delimiter=string("#"," ╔═╡ ")

#export
"""
marks the end of a cell
"""
const _cell_suffix = "\n\n"

#export
"""
> struct ScrubbedNotebook--> Represents a notebook from which all but code to be exported are scrubbed off.
> * Fields-->
>   * cells--> Vector of strings.
"""
mutable struct ScrubbedNotebook
	cells::Array{String, 1}
end

#export
"""
> collect_nuclei(notebook::ScrubbedNotebook, marker)--> Reads a notebook, collects code from code cells and returns an array of Nucelus.
"""
function collect_nuclei(notebook::ScrubbedNotebook, marker)
	notebook_cells=notebook.cells
	nuclei=[]
		
    for i in 1:length(notebook_cells)
    	raw_code=notebook_cells[i]
    	nucleus=Nucleus(raw_code)
    	
    	if startswith(raw_code, marker)
            push!(nuclei,nucleus)
        end
    	
    end
	 nuclei
end

#export
begin
"""
>load_scrubbed_nb(io, path)::ScrubbedNotebook--> These are modification of the Pluto.load_notebook methods. Scrubs the notebook of all stuff but the code to be exported.
"""
function load_scrubbed_nb(io, path)::ScrubbedNotebook
    collected_cells = []
		
	# ignore first bits of file
    readuntil(io,cell_id_delimiter)

    last_read = ""
    while !eof(io)
        cell_id_str = String(readline(io))
        if cell_id_str == "Cell order:"
            break
        else
            code_raw = String(readuntil(io, cell_id_delimiter))
            # change Windows line endings to Linux
            code_normalised = replace(code_raw, "\r\n" => "\n")
            # remove the cell appendix
            code = code_normalised[1:prevind(code_normalised, end, length(_cell_suffix))]

            read_cell = code
            push!(collected_cells, read_cell)
        end
    end
		
	ScrubbedNotebook(collected_cells)
end
	
function load_scrubbed_nb(path::String)::ScrubbedNotebook
    local loaded
    open(path, "r") do io
        loaded = load_scrubbed_nb(io, path)
    end
    loaded
end
end

#export
begin
"""
> load_nb(filename::String, marker::String)--> High level function which calls _load_nb
"""
load_nb(filename::String, marker::String) = _load_nb(filename, marker)

"""
> _load_nb(filename::String, marker::String)--> creates a scrubbed notebook and returns a curated Nb type having code to be exported.
"""
function _load_nb(filename::String, marker::String)
		#notebook=load_notebook_nobackup(filename)
		scrubbedNotebook=load_scrubbed_nb(normpath(joinpath(@__FILE__,"..","..", "nbs", filename)))
		collected_nuclei=nuclei(collect_nuclei(scrubbedNotebook, marker))
		
		#if marker=="md"
		#	notebook
		#else
		Nb(collected_nuclei, filename)
		#end
end

end

#export
"""
> strip --> Helper fucntion to replace a substring y in a string x with blank.
"""
strip=(x::String,y) -> replace(x, y=>"")

#export
begin
"""
> save_nb(io, notebook)--> Reads the supplied notebook and creates an io and writes stuffs like the module name and the content to the created io.
"""
function save_nb(io, notebook)
    println(io, _header)
    println(io, _sub_header)
    println(io, "")
    println(io, "module $(uppercasefirst(strip(strip(notebook.name, r"[0-9_]"), r".jl")))")
	for nucleus in notebook.nuclei
			println(io, nucleus.code*"\n")
    end
	#notebook
	print(io, "end")	
end

"""
> save_nb(notebook::Nb, path::String)--> Creates a file in the supplied path with the name in the NB type.
"""
function save_nb(notebook::Nb, path::String)
	file_name=uppercasefirst(strip(notebook.name, r"[0-9_]"))
	open(joinpath(path, file_name), "w") do io
        save_nb(io, notebook)
    end
end
end

#export
begin
"""
> readfilenames()--> Reads files in the directory and subdirectories in the current path. Reads only the files with ".jl" extension
"""
function readfilenames()
	files=[]
	for file in readdir(normpath(joinpath(@__FILE__,"..","..", "nbs")))
			if endswith(file, ".jl") && !contains(file, "index")
				push!(files,file)
			end
			#if getfile_extension(file)== ".jl"
			#	push!(files,file)
			#end
	end
	files
end

function readfilenames(dir::String)
	files=[]
	for file in readdir(dir)
			if endswith(file, ".jl")
				push!(files,file)
			end
			#if getfile_extension(file)== ".jl"
			#	push!(files,file)
			#end
	end
	files
end
end

#export
"""
> export_file(file::String, path::String, marker::String)--> Loads the file in the supplied path and reads the cells which are marked with "#export". Then saves the notebook in the given path
"""
function export_file(file::String, path::String, marker::String)
	notebook=load_nb(file, "#export")
	save_nb(notebook, path)
end

#export
"""
> export_content(files::AbstractVector, path::String, marker::String)--> maps the `export_file` function to each files
"""
function export_content(files::AbstractVector, path::String, marker::String)
	map(file->export_file(file, path, marker), files)
end

#export
"""
> getfile_extension(filename)--> get the file extensions in the pwd
"""
function getfile_extension(filename)
    return filename[findlast(isequal('.'),filename):end]
end

#export
"""
> notebook2script()--> Export all the code to the ../src path of the project
"""
function notebook2script()
	export_content(readfilenames(), "../src", "#export")
end

end