globals;
addpath('utils/');
addpath('weibull/');
addpath(genpath(CONFIG.detectorCode));
clusterSource = CONFIG.processedSource;
detectionSource = [CONFIG.processedSource '/detections/'];
normalSource = CONFIG.normalSource;
evaluationTargetBasePath = [CONFIG.processedSource '/detectionsEval/'];
splitPart = 'train/';

%when something counts as a positive and as a negative
angleThreshold = deg2rad(30);
doMaskedTransfer = 1;

if ~exist(evaluationTargetBasePath)
    mkdir(evaluationTargetBasePath);
end

doStages = [1, 1, 1];

if (doStages(1))
    myRandomize;

    %load the cluster data
    clusterSplitPath = [clusterSource '/'];
    clusterData = loadRankedClusters(clusterSplitPath, 1.0);

    detectionSplitPath = [detectionSource '/' splitPart '/'];
    images = dir([detectionSplitPath '/*.mat']);

    %make the splits
    splitTarget = [evaluationTargetBasePath '/'];
    if ~exist(splitTarget)
        mkdir(splitTarget);
    end

    splitTarget = [splitTarget '/' splitPart];
    if ~exist(splitTarget)
        mkdir(splitTarget);
    end

    detectionOrder = randperm(numel(images));

    parfor imageII=1:numel(images)
        imageI = detectionOrder(imageII);
        fprintf('Handling %d (%d): ', imageII, imageI);
        originalFilename = strrep(images(imageI).name,'.mat','');
        target = [splitTarget '/' originalFilename '.mat'];
        lockFile = [target '.lock'];
        if exist(target) || isLocked(lockFile)
            fprintf('skipping\n');
            continue;
        end
        fprintf('running\n');

        detections = flattenDetections(load([detectionSplitPath '/' images(imageI).name]));
        detectionAccuracies = ones(size(detections,1),1)*pi;
       
        normalFilename = strrep(strrep(originalFilename, 'rgb','nm'),'.jpg','.mat');
        gtData = load([normalSource '/' normalFilename]);
        gtNormal = zeros(size(gtData.nx,1), size(gtData.nx,2), 3);
        gtNormal(:,:,1) = gtData.nx; gtNormal(:,:,2) = gtData.ny; gtNormal(:,:,3) = gtData.nz;
        gtValid = gtData.depthValid;

        for i=1:size(detections,1)
            %unpack the row to more sensible names
            clusterId = detections(i,1); score = detections(i,2);
            minX = detections(i,3); maxX = detections(i,5);
            minY = detections(i,4); maxY = detections(i,6);
            if ~clusterData.active(clusterId) 
                continue;
            end 
            clusterPatch = clusterData.medianPatches{clusterId}.medianPatch;
            clusterPatch = cat(3, clusterPatch.patchNx, clusterPatch.patchNy,...
                                  clusterPatch.patchNz);
            %get the ground-truth patch
            gtPatch = gtNormal(minY:maxY,minX:maxX,:);
            compareIndicator = gtValid(minY:maxY,minX:maxX);

            if(doMaskedTransfer)
                %if we're doing a masked transfer, only consider the stuff below
                %the angle threshold
                meanErrMask = imresize(clusterData.patchStats{clusterId}.patchStats.thetaMean,[maxY-minY+1,maxX-minX+1]) < angleThreshold;
                compareIndicator = (compareIndicator .* meanErrMask) == 1;
            end 
            %compute the patch distance
            detectionAccuracies(i) = comparePatchToGTPatch(clusterPatch, gtPatch, compareIndicator);
        end
        saveToMat(target, 'detectionAccuracies',detectionAccuracies);

        unlock(lockFile);
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Compute precision curves
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if(doStages(2))
    clusterSplitPath = [clusterSource '/'];
    metadataTarget = [clusterSource '/metadata/'];
    clusterDataSource = [metadataTarget '/detectionAccuracy.mat'];
    precisionTarget = [metadataTarget '/precisionVSVM.mat'];
    
    if ~exist(clusterDataSource)
        %if we don't have the cluster data pre-computed, compute it

        clusterData = loadRankedClusters(clusterSplitPath, 1.0);

        detectionSplitPath = [detectionSource '/' splitPart '/'];
        images = dir([detectionSplitPath '/*.mat']);

        splitTarget = [evaluationTargetBasePath '/' splitPart '/'];

        clusterDetections = cell(numel(clusterData.clusterDirectory),1);

        for i=1:numel(clusterDetections)
            clusterDetections{i} = [];
        end

        for imageI=1:numel(images)
            fprintf('Handling %d\n', imageI);
            originalFilename = strrep(images(imageI).name,'.mat','');
            reducedName = strrep(originalFilename,'.jpg','');
            detectionScoreData = load([splitTarget '/' originalFilename '.mat']);
            detectionAccuracies = min(detectionScoreData.detectionAccuracies,2*pi);
            detections = flattenDetections(load([detectionSplitPath '/' images(imageI).name]));

            for i=1:size(detections,1)
                %unpack the row to more sensible names
                clusterId = detections(i,1); score = detections(i,2);
                minX = detections(i,3); maxX = detections(i,5);
                minY = detections(i,4); maxY = detections(i,6);

                if sum(strcmp(reducedName,clusterData.imageNames{clusterId}))
                    %if the current image matches up with the file, ignore it
                    continue;
                end 
               
                clusterDetections{clusterId} = [clusterDetections{clusterId}; score, detectionAccuracies(i)];

            end
        end
        clusterDetectionEval = clusterDetections;
        save(clusterDataSource,'clusterDetectionEval');
    else
        load(clusterDataSource);
    end
    %so we have clusterDetectionEval, now do scaling

    if(~exist(precisionTarget))
        maxPrecisions = zeros(numel(clusterDetectionEval),1);
        pcs = cell(numel(clusterDetectionEval),1);
        for i=1:numel(clusterDetectionEval)
            detectionsAndAccuracies = sortrows(clusterDetectionEval{i},-1);
            isCorrect = detectionsAndAccuracies(:,2) < angleThreshold;
            cumulativePrecision = cumsum(isCorrect) ./ (1:numel(isCorrect))';
            maxPrecisions(i) = max(cumulativePrecision(5:end));
            pcs{i} = [detectionsAndAccuracies(:,1), cumulativePrecision];
        end 
        precisionVSVMScore = pcs;
        save(precisionTarget, 'precisionVSVMScore');
    end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Finally, do weibull calibration
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if doStages(3)
    clusterSplitPath = [clusterSource  '/'];
    metadataTarget = [clusterSource '/metadata/'];
    precisionData = [metadataTarget '/precisionVSVM.mat'];
    load(precisionData);
    weibullParams = cell(size(precisionVSVMScore));
    calibratedScores = cell(size(precisionVSVMScore));
    for i=1:numel(precisionVSVMScore)
        scoresPrec = precisionVSVMScore{i};
        cutoff = max(find(scoresPrec(:,2) > 0.75));
        if numel(cutoff) == 0
            cutoff = 1;
        end
        cutoff = min(cutoff, fix(size(scoresPrec,1) / 2));
        scoresTail = scoresPrec(cutoff:end,1);
        scoresTail = scoresPrec(fix(size(scoresPrec,1)/2):end,1);
        weibullParams{i} = weibull_fit(scoresTail, 0.5, 0.2);
        wparams = weibullParams{i};
%        calibratedScores{i} = [weibull_cdf(scoresPrec(:,1),weibullParams{i})', scoresPrec(:,2)];
        calibratedScores{i} = [wblcdf(scoresPrec(:,1)+wparams.bias,wparams.a,wparams.b), scoresPrec(:,2)];
    end
    save([metadataTarget '/CalibratedScores.mat'],'calibratedScores','weibullParams');
end
