### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file includes functions for configuring the model and reading in map files.
###

## Note: much of this code was adapted from the GeMM model by Leidinger et al.
## (https://github.com/CCTB-Ecomods/gemm/blob/master/src/input.jl)

let settings::Dict{String, Dict{String, Any}}
    """
        initsettings(configfile)

    Initialise the global model settings for this run.
    """
    global function initsettings(configfile::String)
        settings = getsettings(configfile)
    end
    
    """
        param(domainparam)

    Return a configuration parameter from the global settings.
    The argument should be in the form `"<domain>.<parameter>"`,
    for example `param("core.outdir")`. Possible values for
    <domain> are "core", "ecology", "farm", or "crop".
    """
    global function param(domainparam::String)
        domain, paramname = split(domainparam, ".")
        settings[domain][paramname]
    end

    """
        astoml(io)

    Print all settings in TOML format to the given output stream.
    """
    global function astoml(stream::IO=stdout)
        TOML.print(stream, settings)
    end
end

"""
    getsettings(configfile)

Combines all configuration options to produce a single settings dict.
Precedence: commandline parameters - user config file - default values
"""
function getsettings(configfile::String)
    # read in and merge configurations from the commandline, the default config file
    # and a user-supplied config file
    defaults = TOML.parsefile(configfile)
    commandline = parsecommandline()
    if haskey(commandline, "configfile") && isfile(commandline["configfile"])
        configs = TOML.parsefile(commandline["configfile"])
    else
        configs = nothing
    end
    settings = deepcopy(defaults)
    for domain in keys(defaults)
        for param in keys(defaults[domain])
            if param in keys(commandline)
                settings[domain][param] = commandline[param]
            elseif !isnothing(configs) && param in keys(configs[domain])
                settings[domain][param] = configs[domain][param]
            end
        end
    end
    # pre-process certain parameters
    if settings["core"]["seed"] == 0
        settings["core"]["seed"] = abs(rand(RandomDevice(), Int32))
    end
    defaultoutdir = defaults["core"]["outdir"]
    if settings["core"]["outdir"] == defaultoutdir
        outdir = defaultoutdir*"_"*string(Dates.today())*"_s"*string(settings["core"]["seed"])
        settings["core"]["outdir"] = outdir
    end
    settings
end

"""
    parsecommandline()

Certain software parameters can be set via the commandline.
"""
function parsecommandline()
    s = ArgParseSettings()
    @add_arg_table! s begin
        "--configfile", "-c"
            help = "name of the config file"
            arg_type = String
            required = false
        "--seed", "-s"
            help = "inital random seed"
            arg_type = Int
        "--mapfile", "-m"
            help = "name of the map file"
            arg_type = String
            required = false
        "--outdir", "-o"
            help = "location of the output directory"
            arg_type = String
            required = false
        "--loglevel", "-l"
            help = "verbosity: \"debug\", \"normal\", or \"errors\""
            arg_type = String
            required = false
        "--runtime", "-r"
           help = "duration in days that the simulation will run"
           arg_type = Int
           required = false
    end
    args = parse_args(s)
    for a in keys(args)
        (args[a] == nothing) && delete!(args, a)
    end
    args
end

"""
    readtiffmapfile(filename)

Read in a TIFF map file and return it as an array.
"""
function readtiffmapfile(filename)
    #TODO this requires GeoArrays
end