# 
# v.0.7 (with errors, to be fixed in Pccf2)
#
module Roc

function makeBinsOneSide(changes, maxDelay)
    # returns an array of tuples
    [(c,b) for (c,b) in zip(changes, [c + maxDelay for c in changes])]
end

function makeBinsTwoSide(changes, maxDelay)
    # returns an array of tuples
    right=[c+maxDelay for c in changes]
    left=[c-maxDelay for c in changes]
    [(l,r) for (l,r) in zip(left,right)]
end

function makeBins(changes,maxDelay)
    makeBinsTwoSide(changes,maxDelay)
end

function fallsInBins(val,bins::Array{Tuple{Int64,Int64}})
    # returns bins as an array of tuples: [(left,right)]
    bins[[e[1]<=val<=e[2] for e in bins]]
end
# println(fallsInBins(18, makeBins([1,20,30],3))) 

function ifCdeFallsIntoBins(cde::Int64, bins::Array{Tuple{Int64,Int64}})
    length(fallsInBins(cde, bins))>0 ? true : false 
end
# println(ifCdeFallsIntoBins(18, makeBins([1,20,30],3))) 

function tpNum(detections,changes,maxDelay)
    # Calculate number of true positives
    bins = makeBins(changes, maxDelay)
    cdesInBins = Set(filter(cde->ifCdeFallsIntoBins(cde, bins), detections))
    length(cdesInBins)
end
#
function tpNum(detections,changes)
    intersect(Set(detections), Set(changes))
end

function faNum(detections,changes,maxDelay)
    length(detections)-tpNum(detections,changes,maxDelay)
end

function fnNum(detections,changes,maxDelay)
    # Calculate number of false negatives
    bins=makeBins(changes.maxDelay)
    length(bins)-tpNum(detections, changes, maxDelay)
end

function tpRate(detections,changes,maxDelay)
    # True positive TP rate = TP/(TP + FN); In case if there are
    # several true changes within the same bin we take min(1, tprate)
    tpn=tpNum(detections,changes,maxDelay)
    min(1, tpn/length(changes))
end

function faRate(detections,changes,maxDelay,totalNum)
    # False alarm/positive rate FPR = FP / (FP + TN) ; == specificity
    fan = faNum(detections,changes,maxDelay)
    tpn = tpNum(detections,changes,maxDelay)
    trueNegNum = totalNum - length(changes) * maxDelay
    fan/(fan+trueNegNum)
end

end
