### Persefone.jl - a model of agricultural landscapes and ecosystems in Europe.
###
### Daniel Vedder <daniel.vedder@idiv.de>
### Guy Pe'er <guy.peer@idiv.de>
### https://git.idiv.de/persefone/persefone-model
### (c) 2022-2023, licensed under the terms of the MIT license
###
### This file defines the module/package for the Persefone model.
### To run the model, either execute `run.jl` from the commandline,
### or import the module using your own wrapper script or software.
###

module Persefone

## define dependencies
using
    ArgParse,
    CairoMakie, #XXX this is a very big dependency :-(
    CSV,
    Dates,
    DataFrames,
    DataFramesMeta,
    Distributed,
    FileIO,
    GeoArrays, #XXX this is another big dependency - replace with Rasters.jl?
    Logging,
    LoggingExtras,
    Random,
    Serialization,
    StableRNGs,
    TOML,
    Unitful

## Packages that may be useful later on:
# MacroTools, http://fluxml.ai/MacroTools.jl/stable/utilities/
# Debugger, https://github.com/JuliaDebug/Debugger.jl
# PackageCompiler, https://julialang.github.io/PackageCompiler.jl/stable/
# SpatialEcology, https://github.com/EcoJulia/SpatialEcology.jl
# PlantSimEngine, https://virtualplantlab.github.io/PlantSimEngine.jl/stable/
# Overseer, https://juliapackages.com/p/overseer -> ECS

## define exported functions and variables
export
    #types
    AnnualDate,
    Pixel,
    Weather,
    FarmEvent,
    ModelAgent,
    FarmPlot,
    Animal,
    Farmer,
    DataOutput,
    SimulationModel,
    AgricultureModel,
    #macros
    @param,
    @rand,
    @shuffle!,
    @thisyear,
    @nextyear,
    @lastyear,
    @record,
    @data,
    @species,
    @populate,
    @create,
    @phase,
    @animal,
    @isalive,
    @here,
    @setphase,
    @respond,
    @kill,
    @killother,
    @reproduce,
    @migrate,
    @occupy,
    @isoccupied,
    @vacate,
    @habitat,
    @landcover,
    @cropname,
    @cropheight,
    @cropcover,
    @directionto,
    @distanceto,
    @distancetoedge,
    @randompixel,
    @randomdirection,
    @nearby_animals,
    @countanimals,
    @neighbours,
    @move,
    @walk,
    @follow,
    @destroynest,
    @sow,
    @harvest,
    #functions
    simulate,
    simulate!,
    initialise,
    stepsimulation!,
    createevent!,
    finalise!,
    outputdata,
    visualisemap,
    populationtrends,
    visualiseoutput,
    savemodelobject,
    loadmodelobject,
    croptype,
    cropname,
    cropheight,
    cropcover,
    cropyield

"""
    SimulationModel

The supertype of [AgricultureModel](@ref). This is needed to avoid circular
dependencies (most types and functions depend on `SimulationModel`, but the
definition of the model struct depends on these types).
"""
abstract type SimulationModel end

"""
    ModelAgent

The supertype of all agents in the model (animal species, farmer types, farmplots).
"""
abstract type ModelAgent end

"""
    AbstractCropType

The abstract supertype of all crop types in the model.  Each crop
model has to define a type `CropType <: AbstractCropType`.
"""
abstract type AbstractCropType end

"""
    AbstractCropState

The abstract supertype of all crop states in the model.  Each crop
model has to define a type `CropState <: AbstractCropState`.
"""
abstract type AbstractCropState end

function makecropstate end
setsoiltype!(cropstate::AbstractCropState, soiltype) = nothing

function stepagent! end

## include all module files (note that the order matters - if file
## b references something from file a, it must be included later)
include("core/utils.jl")
include("core/input.jl")
include("core/output.jl")

include("world/landscape.jl")
include("world/weather.jl")

include("crop/farmplot.jl")
include("crop/cropmodels.jl")
include("crop/almass.jl")
include("crop/simplecrop.jl")
include("crop/aquacrop.jl")

include("farm/farm.jl")
include("farm/farmdata.jl")

include("nature/insects.jl")
include("nature/energy.jl")
include("nature/nature.jl")
include("nature/macros.jl")
include("nature/populations.jl")
include("nature/individuals.jl")
include("nature/ecologicaldata.jl")
include("nature/species/skylark.jl")
include("nature/species/wolpertinger.jl")
include("nature/species/wyvern.jl")

include("analysis/makieplots.jl")

include("core/simulation.jl") #this must be last

# precompile important functions - TODO use PrecompileTools.jl
precompile(initialise, (String,Int))
precompile(stepsimulation!, (SimulationModel,))

end