import AquaCrop

# We can't use Length{Float64} as that is a Union type
const Tlength = typeof(1.0cm)

struct AquaCropType
    name::String
    group::String
    minsowdate::Union{Missing,AnnualDate}
    maxsowdate::Union{Missing,AnnualDate}
end

cropname(ct::AquaCropType) = ct.name

mutable struct AquaCropState
    croptype::AquaCropType
    height::Length{Float64}  # TODO: remove height field, supply from cropstate
    cropstate::AquaCrop.AquaCropField

    function AquaCropState(croptype::AquaCropType, height::Length{Float64}=0.0cm)
        runtype = AquaCrop.TomlFileRun()
        parentdir = AquaCrop.test_toml_dir  # TODO: hardcoded croptype
        ac_cropfield, all_ok = AquaCrop.start_cropfield(; parentdir, runtype)
        if ! all_ok.logi
            error("AquaCrop.start_cropfield() failed, status = $all_ok")
        end
        AquaCrop.setup_cropfield!(ac_cropfield, all_ok; runtype=runtype)
        if ! all_ok.logi
            error("AquaCrop.setup_cropfield!() failed, status = $all_ok")
        end
        return new(croptype, height, ac_cropfield)
    end
end

croptype(cs::AquaCropState) = cs.croptype
cropname(cs::AquaCropState) = cropname(croptype(cs))
cropheight(cs::AquaCropState) = cs.height  # TODO: use AquaCrop state info
cropcover(cs::AquaCropState) = AquaCrop.canopycover(cs.cropstate)
cropyield(cs::AquaCropState) = AquaCrop.dryyield(cs.cropstate)  # TODO: there is also freshyield
isharvestable(cs::AquaCropState) = true  # TODO: implement this correctly

"""
    stepagent!(cropstate, model)

Update a crop state by one day.
"""
function stepagent!(cs::AquaCropState, model::SimulationModel)
    AquaCrop.dailyupdate!(cs.cropstate)
end

"""
    sow!(cropstate, model, cropname)

Change the cropstate to sow the specified crop.
"""
function sow!(cs::AquaCropState, model::SimulationModel, cropname::String)
    cs.croptype = model.crops[cropname]
    cs.height = 0.0cm
    # TODO: other things needed for AquaCrop?
end

"""
    harvest!(cropstate, model)

Harvest the crop of this cropstate.
"""
function harvest!(cs::AquaCropState, model::SimulationModel)
    # TODO: implement this
    return 0.0u"g/m^2"
end