
module Verbose_print
    import InteractiveUtils
    abstract type Verbose_level end

    struct Verbose_3  <: Verbose_level
        fp::Union{Nothing,IOStream}
        Verbose_3() = new(nothing)
        Verbose_3(filename::String) = new(open(filename,"w"))
        Verbose_3(fp::IOStream) = new(fp)
    end

    struct Verbose_2  <: Verbose_level
        fp::Union{Nothing,IOStream}
        Verbose_2() = new(nothing)
        Verbose_2(filename::String) = new(open(filename,"w"))
        Verbose_2(fp::IOStream) = new(fp)
    end

    struct Verbose_1  <: Verbose_level
        fp::Union{Nothing,IOStream}
        Verbose_1() = new(nothing)
        Verbose_1(filename::String) = new(open(filename,"w"))
        Verbose_1(fp::IOStream) = new(fp)
    end

    function Base.flush(v::Verbose_level)
        if v.fp != nothing
            flush(v.fp)
        end
    end

    function InteractiveUtils.versioninfo(v::Verbose_level)
        InteractiveUtils.versioninfo()
        if v.fp != nothing
            InteractiveUtils.versioninfo(v.fp)
        end
    end



    function println_verbose1(v::Verbose_3,val...)
        println(val...)
        if v.fp != nothing
            println(v.fp,val...)
        end
    end

    function println_verbose2(v::Verbose_3,val...)
        println(val...)
        if v.fp != nothing
            println(v.fp,val...)
        end
    end

    function println_verbose3(v::Verbose_3,val...)
        println(val...)
        if v.fp != nothing
            println(v.fp,val...)
        end
    end

    function println_verbose1(v::Verbose_2,val...)
        println(val...)
        if v.fp != nothing
            println(v.fp,val...)
        end
    end

    function println_verbose2(v::Verbose_2,val...)
        println(val...)
        if v.fp != nothing
            println(v.fp,val...)
        end
    end

    function println_verbose3(v::Verbose_2,val...)
        return 
    end

    function println_verbose1(v::Verbose_1,val...)
        println(val...)
        if v.fp != nothing
            println(v.fp,val...)
        end
    end

    function println_verbose2(v::Verbose_1,val...)
        return
    end

    function println_verbose3(v::Verbose_1,val...)
        return 
    end

    function print_verbose1(v::Verbose_3,val...)
        print(val...)
        if v.fp != nothing
            print(v.fp,val...)
        end
    end

    function print_verbose2(v::Verbose_3,val...)
        print(val...)
        if v.fp != nothing
            print(v.fp,val...)
        end
    end

    function print_verbose3(v::Verbose_3,val...)
        print(val...)
        if v.fp != nothing
            print(v.fp,val...)
        end
    end

    function print_verbose1(v::Verbose_2,val...)
        print(val...)
        if v.fp != nothing
            print(v.fp,val...)
        end
    end

    function print_verbose2(v::Verbose_2,val...)
        print(val...)
        if v.fp != nothing
            print(v.fp,val...)
        end
    end

    function print_verbose3(v::Verbose_2,val...)
        return 
    end

    function print_verbose1(v::Verbose_1,val...)
        print(val...)
        if v.fp != nothing
            print(v.fp,val...)
        end
    end

    function print_verbose2(v::Verbose_1,val...)
        return
    end

    function print_verbose3(v::Verbose_1,val...)
        return 
    end
end
