# Written by Nishant Mittal aka nishantwrp

# Imports
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.gaussian_process.kernels import RBF

# Constants
LABELS = 7

def check_probabilities(original_prob, new_prob, alpha, labels, target_label):
    '''
    Checks if probabilites generated by current value of f are acceptable for a particular label
    '''
    for i, original_prob_obj in enumerate(original_prob):
        original_prob_list = list(original_prob_obj)
        new_prob_list = list(new_prob[i])

        if labels[i] == target_label:
            if ((alpha*max(original_prob_list)) > max(new_prob_list)):
                return False

    return True

def calculate_mrl(X, Y, alpha, initial_f):
    '''
    Calculates the mrl for a component
    '''
    kernel = 1.0 * RBF(1.0)
    gpc = GaussianProcessClassifier(kernel=kernel, random_state=0).fit(X, Y)
    original_prob = gpc.predict_proba(X)
    print("Probabilities for the complete MTS calculated")

    mrl = [None for _ in range(LABELS)]

    current_f = initial_f
    while True:
        gpc = GaussianProcessClassifier(kernel=kernel, random_state=0).fit(X[:, :current_f], Y)
        new_prob = gpc.predict_proba(X[:, :current_f])
        print("Probabilities calculated when value of F is %s" % (str(current_f)))

        for i, mrl_value in enumerate(mrl):
            if not (mrl_value):
                if check_probabilities(original_prob, new_prob, alpha, Y, i+1):
                    mrl[i] = current_f
                    print("F for label %s is %s" % (str(i+1), str(current_f)))

        all_values_are_found = True
        for mrl_value in mrl:
            if not (mrl_value):
                all_values_are_found = False

        if (all_values_are_found):
            break

        current_f += 1

    return mrl

def get_gpc(X, Y):
    '''
    Train and return the gaussian process classifier for the given data
    '''
    kernel = 1.0 * RBF(1.0)
    gpc = GaussianProcessClassifier(kernel=kernel, random_state=0).fit(X, Y)
    return gpc

def get_labels_prob_for_one_series(series, classifiers, mrls):
    '''
    Get labels, probability, data_points used for each sensor.
    '''
    previous_label = 1
    max_data_points_used = 0
    predicted_labels = list()
    predicted_probs = list()

    for ci in range(len(series)):
        data_points_to_use = mrls[ci][previous_label-1]
        max_data_points_used = max(max_data_points_used, data_points_to_use)

        data_component = series[ci]
        data_component = data_component[:data_points_to_use]
        classifier = classifiers[ci][previous_label-1]

        predicted_label =  classifier.predict([data_component])[0]
        predicted_prob = classifier.predict_proba([data_component])[0]

        predicted_labels.append(predicted_label)
        predicted_probs.append(predicted_prob)
        previous_label = predicted_label

    return predicted_labels, predicted_probs, max_data_points_used
