module Test

using Test, GridArrays, DomainSets

using GridArrays: hasextension, extend, rescale

function test_interval_grid(grid::AbstractGrid, show_timings=false)
    test_generic_grid(grid, show_timings=show_timings)
    T = eltype(grid)
    g1 = rescale(rescale(grid, -T(10), T(3)), infimum(covering(grid)), supremum(covering(grid)))
    @test covering(g1) ≈ covering(grid)
    g2 = resize(grid, length(grid)<<1)
    @test length(g2) == length(grid)<<1

    g3 = resize(g1, length(grid)<<1)
    @test length(g3) == length(grid)<<1

    g4 = rescale(rescale(g2, -T(10), T(3)), infimum(covering(g2)), supremum(covering(g2)))
    @test covering(g4) ≈ covering(g2)

    if hasextension(grid)
        @test extend(grid,3) isa typeof(grid)
    end
    if grid isa AbstractEquispacedGrid
        @test step(grid) ≈ grid[2]-grid[1]
    end
end

function test_generic_grid(grid; show_timings=false)
    io = IOBuffer()
    show(io, grid)
    @test length(take!(io))>0
    L = length(grid)
    @test ndims(grid) == length(grid[1])

    T = eltype(grid)
    FT = prectype(T)

    grid_iterator(grid)

    # Test two types of iterations over a grid.
    # Make sure there are L elements. Do some computation on each point,
    # and make sure the results are the same.
    (l1,sum1) = grid_iterator1(grid)
    @test l1 == L
    (l2,sum2) = grid_iterator2(grid)
    @test l2 == L
    @test sum1 ≈ sum2

    if typeof(grid) <: AbstractGrid1d
        # Make sure that 1d grids return points, not vectors with one point.
        @test eltype(grid) <: Number
    end

    if hasextension(grid)
        g_ext = extend(grid, 2)
        @test grid ≈ g_ext[1:2:end]
        # for i in 1:length(grid)
        #     @test grid[i] ≈ g_ext[2i-1]
        # end
    end

    if show_timings
        t = @timed grid_iterator1(grid)
        t = @timed grid_iterator1(grid)
        print_with_color(:blue, "Eachindex: ")
        println(t[3], " bytes in ", t[2], " seconds")
        t = @timed grid_iterator2(grid)
        print_with_color(:blue, "Each x in grid: ")
        println(t[3], " bytes in ", t[2], " seconds")
    end
end

function grid_iterator(grid)
    grid_iteration_equal = true
    for (i,j) in zip(1:length(grid), eachindex(grid))
        grid_iteration_equal &= grid[i] == grid[j]
    end
    @test grid_iteration_equal
end

function grid_iterator1(grid)
    l = 0
    s = zero(prectype(grid))
    for i in eachindex(grid)
        x = grid[i]
        l += 1
        s += sum(x)
    end
    (l,s)
end

function grid_iterator2(grid)
    l = 0
    s = zero(prectype(grid))
    for x in grid
        l += 1
        s += sum(x)
    end
    (l,s)
end

end
