import numpy as np


def binary_classification_metrics(prediction, ground_truth):
    '''
    Computes metrics for binary classification

    Arguments:
    prediction, np array of bool (num_samples) - model predictions
    ground_truth, np array of bool (num_samples) - true labels

    Returns:
    precision, recall, f1, accuracy - classification metrics
    '''

    def inverse(bool_array):
        return bool_array == False

    true_positive = np.sum(ground_truth[prediction])
    false_negative = np.sum(ground_truth[inverse(prediction)])
    false_positive = np.sum(inverse(ground_truth[prediction]))
    true_prediction = np.sum(prediction == ground_truth)

    precision = true_positive / (true_positive + false_positive)
    recall = true_positive / (true_positive + false_negative)
    accuracy = true_prediction / len(prediction)
    f1 = 2 * (precision * recall) / (precision + recall)

    # TODO_: implement metrics!
    # Some helpful links:
    # https://en.wikipedia.org/wiki/Precision_and_recall
    # https://en.wikipedia.org/wiki/F1_score
    
    return accuracy, precision, recall, f1


def multiclass_accuracy(prediction, ground_truth):
    """
    Computes metrics for multiclass classification

    Arguments:
    prediction, np array of int (num_samples) - model predictions
    ground_truth, np array of int (num_samples) - true labels

    Returns:
    accuracy - ratio of accurate predictions to total samples
    """
    accuracy = np.sum(prediction == ground_truth) / len(ground_truth)

    return accuracy
