"""Calculate the mean additional error.

Accepts a csv file generated by generate_score_csvs, and outputs
additional error risk at all coverages, as well as the area under
the additional error risk curve. Called from run_analysis.py

Typical usage:
    ARCalc(outfile)
"""
import csv
import wandb

# pylint: disable=consider-using-enumerate

class AECalc():
    """Calculates additional error and AMAE.
    """
    def __init__(self, in_csv):
        """Initializes the AECalc class and performs MAE calculations.

        Args:
            in_csv: The CSV generated by generate_score_csvs.
        Returns:
            Nothing. Results are logged to Weights and Biases.
        """
        # Read the csv into a list of samples (represented as dicts)
        with open(in_csv, "r") as infile:
            reader = csv.DictReader(infile)
            sample_list = []
            for line in reader:
                line_dict = {'score':float(line['score']),\
                             'loss_delta':float(line['loss_delta']),\
                             'geodesic_delta':float(line['geodesic_delta']),\
                             'keypoint_dist':float(line['keypoint_dist'])}
                sample_list.append(line_dict)

        # sort the list based on the scoring function
        sorted_list = sorted(sample_list, key=lambda k: k['score'])

        current_ar_geodesic = 0 # additional risk (cumulative)

        # running areas under the curve (cumulative)
        running_auc_method_geodesic = 0

        for i in range(len(sorted_list)):
            # Coverage increases by 1/samples for every sample.
            coverage = (1.+i)/len(sorted_list)

            # The numerator of the additional risk term. Is divided by
            # the coverage both at the output (wandb log) and in the AUC
            # calculation.
            current_ar_geodesic += 1./len(
                sorted_list)*max(
                    sorted_list[i]['geodesic_delta'], 0)

            # the AUC is the additional risk at every step (which
            # requires dividing by coverage), times the width of the
            # step (1/#samples)
            running_auc_method_geodesic += current_ar_geodesic\
                    /coverage * 1./len(sorted_list)

            # log to WandB
            wandb.log({'coverage':coverage,
                       'additional_risk_geodesic':
                       current_ar_geodesic/coverage,
                       'auc_geodesic':running_auc_method_geodesic})
