### Persefone.jl - a model of agricultural landscapes and ecosystems in Europe.
###
### Functions for switchable crop models.
###

"""
    initfields!(cropmodel, cropfile, growthfile)

Initialise the crop model.  Returns the crop types available in the
simulation, as well as the types `Tcroptype` and `Tcropstate`.
"""
function initcropmodel(cropmodel::AbstractString, cropdirectory::AbstractString)
    if cropmodel == "almass"
        Tcroptype = ALMaSS.CropType
        Tcropstate = ALMaSS.CropState
        crops = ALMaSS.readcropparameters(cropdirectory)
    elseif cropmodel == "simple"
        Tcroptype = SimpleCrop.CropType
        Tcropstate = SimpleCrop.CropState
        crops_almass = ALMaSS.readcropparameters(cropdirectory)
        crops = Dict(name => SimpleCrop.CropType(ct.name, ct.group, ct.minsowdate, ct.maxsowdate)
                     for (name, ct) in crops_almass)
    else
        error("initcropmodel: no implementation for crop model '$cropmodel'")
    end
    return crops, Tcroptype, Tcropstate
end

"""
    initfields!(model)

Initialise the farm plots in the simulation model.
"""
function initfields!(model::SimulationModel)
    convertid = Dict{Int64,Int64}()
    width, height = size(model.landscape)
    for x in 1:width
        for y in 1:height
            # for each pixel, we need to extract the field ID given by the map input
            # file, and convert it into an internal object ID for `model.farmplots`
            rawid = model.landscape[x,y].fieldid
            (ismissing(rawid)) && continue
            if rawid in keys(convertid)
                objectid = convertid[rawid]
                model.landscape[x,y].fieldid = objectid
                push!(model.farmplots[objectid].pixels, (x,y))
            else
                cropstate = makecropstate(model)
                fp = FarmPlot(length(model.farmplots) + 1, [(x, y)], -1, cropstate)
                push!(model.farmplots, fp)
                model.landscape[x,y].fieldid = fp.id
                convertid[rawid] = fp.id
            end
        end
    end
    @info "Initialised $(length(model.farmplots)) farm plots."
end

"""
    makecropstate(model, cropmodel)

An internal utility function to initialise one instance of the configured crop growth model.
"""
function makecropstate(model::SimulationModel)
    if @param(crop.cropmodel) == "almass"
        phase = (month(model.date) < 3 ? ALMaSS.janfirst : ALMaSS.marchfirst)
        cs = ALMaSS.CropState(
            croptype = model.crops["natural grass"],
            phase = phase,
        )
    elseif @param(crop.cropmodel) == "simple"
        cs = SimpleCrop.CropState(
            model.crops["natural grass"],
            0.0m
        )
    else
        Base.error("Unhandled crop model '$(@param(crop.cropmodel))' in makecropstate().")
    end
    return cs
end