### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### These are the tests for the core landscape functions.
###

"""
    smalltestlandscape()

Create a 6x6 landscape with three land cover types for testing:

    F F F F F F
    F F F F F F
    F F F F F F
    F F F F F W
    F F G G G G
    F F G G G G
"""
function smalltestlandscape(agenttype::Type=Animal)
    landscape = Matrix{Pixel}(undef, 6, 6)
    for x in 1:6
        for y in 1:6
            (x in (1:2) || y in (1:4)) ? lc = Ps.forest : lc = Ps.grass
            landscape[x,y] = Pixel(lc, missing, [])
        end
    end
    landscape[6,4] = Pixel(Ps.water, 0, [])
    space = GridSpace(size(landscape), periodic=false)
    properties = Dict{Symbol,Any}(:date=>TESTSETTINGS["core"]["startdate"],
                                  :landscape=>landscape,
                                  :events=>Vector{FarmEvent}(),
                                  :dataoutputs=>Vector{DataOutput}(),
                                  :settings=>TESTSETTINGS)
    return AgentBasedModel(agenttype, space, properties=properties, warn=false)
end

@testset "Landscape initialisation" begin
    # initialise the landscape part of the model
    landscape = Ps.initlandscape(TESTSETTINGS["core"]["landcovermap"],
                                 TESTSETTINGS["core"]["farmfieldsmap"])
    space = GridSpace(size(landscape), periodic=false)
    properties = Dict{Symbol,Any}(:landscape=>landscape, :settings=>TESTSETTINGS)
    model = AgentBasedModel(FarmPlot, space, properties=properties, warn=false)
    # these tests are specific to the Jena maps
    @test_logs (:info, "Initialised 2092 farm plots.") match_mode=:any Ps.initfields!(model)
    @test size(model.landscape) == (1754, 1602)
    @test Ps.landcover((100,100), model) == Ps.forest
    @test Ps.landcover((300,1), model) == Ps.soil
    @test Ps.landcover((500,1), model) == Ps.nodata
    @test Ps.landcover((400,400), model) == Ps.grass
    @test Ps.landcover((800,800), model) == Ps.agriculture
    @test Ps.landcover((1100,1100), model) == Ps.builtup
    @test Ps.averagefieldsize(model) == 5.37
    @test count(f -> ismissing(f.fieldid), model.landscape) == 1685573
    @test length(Ps.farmplot((800,800), model).pixels) == 4049                
end

@testset "Event system" begin
    model = smalltestlandscape()
    createevent!(model, [(1,1), (1,2), (1,3), (2,1), (2,3)], Ps.tillage)
    createevent!(model, [(1,1), (1,2), (1,3), (2,2)], Ps.sowing, 2)
    @test model.landscape[1,1].events == [Ps.tillage, Ps.sowing]
    @test model.landscape[2,1].events == [Ps.tillage]
    @test model.landscape[2,2].events == [Ps.sowing]
    @test_logs (:info, "Simulating day 2022-01-01.") match_mode=:any stepsimulation!(model)
    @test model.landscape[1,1].events == [Ps.sowing]
    @test model.landscape[2,1].events == []
    @test model.landscape[2,2].events == [Ps.sowing]
    @test_logs (:info, "Simulating day 2022-01-02.") match_mode=:any stepsimulation!(model)
    @test model.landscape[1,1].events == []
    @test model.landscape[2,1].events == []
    @test model.landscape[2,2].events == []
end

@testset "Landscape functions" begin
    model = smalltestlandscape()
    @test Ps.distanceto((2,3), model, Ps.forest) == 0
    @test Ps.distanceto((2,3), model, Ps.grass) == 2
    @test Ps.distanceto((2,3), model, Ps.water) == 4
    @test Ps.distanceto((2,3), model, Ps.soil) == Inf
    @test Ps.distancetoedge((1,1), model) == 4
    @test Ps.distancetoedge((4,4), model) == 1
    @test Ps.distancetoedge((6,6), model) == 2
end