using BinaryProvider
using BinaryBuilder
using Base.Test
using SHA
using Compat

# The platform we're running on
const platform = platform_key()

# On windows, the `.exe` extension is very important
const exe_ext = is_windows() ? ".exe" : ""

# We are going to build/install libfoo a lot, so here's our function to make sure the
# library is working properly
function check_foo(fooifier_path = "fooifier$(exe_ext)",
                   libfoo_path = "libfoo.$(Libdl.dlext)")
    # We know that foo(a, b) returns 2*a^2 - b
    result = 2*2.2^2 - 1.1

    # Test that we can invoke fooifier
    @test !success(`$fooifier_path`)
    @test success(`$fooifier_path 1.5 2.0`)
    @test parse(Float64,readchomp(`$fooifier_path 2.2 1.1`)) ≈ result

    # Test that we can dlopen() libfoo and invoke it directly
    libfoo = Libdl.dlopen_e(libfoo_path)
    @test libfoo != C_NULL
    foo = Libdl.dlsym_e(libfoo, :foo)
    @test foo != C_NULL
    @test ccall(foo, Cdouble, (Cdouble, Cdouble), 2.2, 1.1) ≈ result
    Libdl.dlclose(libfoo)
end

@testset "File Collection" begin
    temp_prefix() do prefix
        # Create a file and a link, ensure that only the one file is returned by collect_files()
        f = joinpath(prefix, "foo")
        f_link = joinpath(prefix, "foo_link")
        touch(f)
        symlink(f, f_link)

        files = collect_files(prefix)
        @test length(files) == 1
        @test files[1] == abspath(f)
    end
end

# This file contains tests that require our cross-compilation environment
@testset "Builder Dependency" begin
    temp_prefix() do prefix
        # First, let's create a Dependency that just installs a file
        cd("build_tests") do
            # Our simple executable file, generated by bash
            test_exe_path = joinpath(bindir(prefix),"test_exe")
            test_exe = ExecutableProduct(test_exe_path)
            results = [test_exe]

            # Remember that we don't need to use `bash()` here because these commands
            # will be happening within the cross-compilation environment
            cmds = Cmd[]
            push!(cmds, `mkdir -p $(bindir(prefix))`)
            push!(cmds, `bash -c "printf '#!/bin/bash\necho test' > $(test_exe_path)"`)
            push!(cmds, `chmod 775 $(test_exe_path)`)
            
            dep = Dependency("bash_test", results, cmds, platform, prefix)

            @test build(dep; verbose=true)
            @test satisfied(dep)
            @test readstring(`$(test_exe_path)`) == "test\n"
        end

        # Next, build a simple shared library and an executable
        cd("build_tests/libfoo") do
            libfoo = LibraryProduct(prefix, "libfoo")
            fooifier = ExecutableProduct(prefix, "fooifier")
            steps = [`make clean`, `make install`]
            dep = Dependency("foo", [libfoo, fooifier], steps, platform, prefix)

            # Build it
            @test build(dep; verbose=true)
            @test satisfied(dep; verbose=true)

            # Test the binaries
            check_foo(locate(fooifier), locate(libfoo))

            # Also test the binaries through `activate()`
            activate(prefix)
            check_foo()
            deactivate(prefix)

            # Test that `collect_files()` works:
            all_files = collect_files(prefix)
            @test locate(libfoo) in all_files
            @test locate(fooifier) in all_files
        end
    end
end

@testset "Builder Packaging" begin
    # Clear out previous build products
    for f in readdir(".")
        if !endswith(f, ".tar.gz")
            continue
        end
        rm(f; force=true)
    end

    # Gotta set this guy up beforehand
    tarball_path = nothing
    tarball_hash = nothing

    temp_prefix() do prefix
        cd("build_tests/libfoo") do
            # First, build libfoo
            libfoo = LibraryProduct(prefix, "libfoo")
            fooifier = ExecutableProduct(prefix, "fooifier")
            steps = [`make clean`, `make install`]
            dep = Dependency("foo", [libfoo, fooifier], steps, platform, prefix)

            @test build(dep)
        end    
        
        # Next, package it up as a .tar.gz file
        tarball_path, tarball_hash = package(prefix, "./libfoo"; verbose=true)
        @test isfile(tarball_path)
    end

    # Test that we can inspect the contents of the tarball
    contents = list_tarball_files(tarball_path)
    @test "bin/fooifier" in contents
    @test "lib/libfoo.$(Libdl.dlext)" in contents

    # Install it within a new Prefix
    temp_prefix() do prefix
        # Install the thing
        @test install(tarball_path, tarball_hash; prefix=prefix, verbose=true)

        # Ensure we can use it
        fooifier_path = joinpath(bindir(prefix), "fooifier")
        libfoo_path = joinpath(libdir(prefix), "libfoo.$(Libdl.dlext)")
        check_foo(fooifier_path, libfoo_path)
    end

    rm(tarball_path; force=true)
end