module Bisect

export idx_of_closest
#export bin_search, idx_of_closest

function midpoint(a, b)
    if a > b
        error("... b must be greater or equal than a; a == $a, b == $b")
    elseif a == b
        a
    else
        div(a + b , 2)
    end
end

#................ 1) Search bin
function search_bin(edges::Vector{Float64}, val::Float64, imin::Int, imax::Int)
    # find the BIN - characterized by the pair of edges
    # If
    imid = midpoint(imin, imax)
    if imin == imax
        if val >= edges[imid]
            imid + 1
        else
            imid
        end
    else
        if val >= edges[imid]
            search_bin(edges, val, imid + 1, imax)
        else
            search_bin(edges, val, imin, max(imid - 1, imin))
        end
    end
end

function search_bin(edges::Vector{Float64}, val::Float64)
    search_bin(edges, val, 1, length(edges))
end

function test_search_bin()
    println( search_bin([0.1, 0.2, 0.3], 0.05)) # 1
    println( search_bin([0.1, 0.2, 0.3], 0.10)) # 2
    println( search_bin([0.1, 0.2, 0.3], 0.15)) # 2
    println( search_bin([0.1, 0.2, 0.3], 0.19)) # 2
    println( search_bin([0.1, 0.2, 0.3], 0.29)) # 3
    println( search_bin([0.1, 0.2, 0.3], 0.31)) # 4
end
# test_search_bin()
#................ End 1) Search bin
#............... 2) Index of the closest element
function idx_of_closest(edges::Vector{Float64}, val::Float64, imin::Int, imax::Int)
    # Find index of the closest edge to the value
    bin  = search_bin(edges, val)
    n = length(edges)
    if bin == 1
        edges[bin]
    elseif bin == n + 1
        edges[n]
    else
        left_dist  = abs(val - edges[bin-1])
        right_dist = abs(val - edges[bin]  )
        left_dist >= right_dist ? bin : bin - 1
    end
end

function idx_of_closest(edges::Vector{Float64}, val::Float64)
    idx_of_closest(edges, val, 1, length(edges))
end

function test_bin_search_closest_idx()
    println( idx_of_closest([0.1, 0.2, 0.5], 0.15))
    println( idx_of_closest([0.1, 0.2, 0.5], 0.16))
end
#test_bin_search_closest_idx()
#............... End 2) Index of the closest element
end
