from __future__ import absolute_import, division, print_function, \
    unicode_literals
import csv
import numpy as np

from sklearn.model_selection import train_test_split
from learning_model import get_compiled_model
from data_processing import DataProcessor


def classify_data(alarm, classification, filepath, dim, inum, dropout, output):
    '''
    Trains on the data passed as input. This function initializes the structure
    of the learning model, specific to the classification label.

            Parameters:
                alarm: encoded alarm values
                classification: label data in the form of numpy array
                filepath: name of the .hdf5 saved model state file
                dim: input dimension for learning model
                inum: number of neurons for input layer
                dropout: dropout rate for learning model
                output: number of output neurons per classification label

    x_data is what is fed into the NN. This will be the encoded alarm
    values for each ticket.

    y_data are the encoded label values that correspond to each ticket.
    '''
    x_data = alarm[:2132]
    y_data = classification[:2132]

    x_train, x_test, y_train, y_test = train_test_split(x_data,
                                                        y_data,
                                                        test_size=0.20,
                                                        random_state=0)

    model = get_compiled_model(dim, inum, dropout, output)

    # Epochs pass the data n times through the system
    history = model.fit(x_train,
                        y_train,
                        epochs=20,
                        batch_size=20,
                        validation_data=(x_test, y_test),
                        verbose=0)

    # saves the model in the filepath listed
    model.save('./models/' + filepath)

    # Eval accuracy of model on test data using the test labels in the file
    test_results = model.evaluate(x_test, y_test)
    train_results = model.evaluate(x_train, y_train)

    print(history.model)
    print("Test Evaluation: " + str(test_results))
    print("Train Evaluation: " + str(train_results))


def convert_test_data(filename, alarm, ticket):
    '''
    Function converts the encoded hex values to numpy arrays.

            Returns: converted data in form of numpy array.

            Parameters:
                filename: prediction filename
                alarm: alarm file required by DataProcessor object
                ticket: ticket file required by DataProcessor object
    '''
    dp = DataProcessor(alarm, ticket)
    test_alarm_values = []
    with open(filename, encoding='utf8') as csv_file:
        reader = csv.reader(csv_file)
        next(reader)
        for row in reader:
            test_alarm_values.append(row[3])

    result_list = []
    for item in test_alarm_values:
        encoded_alarm = dp.encode_hex_values(item)
        result_list.append(encoded_alarm)

    return dp.convert_array_to_np_array(result_list)


def report_prediction_results(predicted, label):
    '''
    This function will take in a data set and provide the labels for the
    maximum confidence label index value. This will report the results as an
    array of values similar to the content of the ticket data file.

            Returns: array of subarrays containing label as a string.

            Parameters:
                predicted: predicted arrays of output generated by the
                           learning model
                label: member of DataProcessor used to retrieve the
                       string representation of the prediction
    '''
    result_arr = []

    length_of_array = len(predicted)
    num_of_vals = len(predicted[0])

    # loops through rows
    for rows in range(length_of_array):
        greatest_percent = max(predicted[rows])
        position = 0

        # gets the index of largest confidence value
        for index in range(num_of_vals):
            if predicted[rows][index] == greatest_percent:
                position = index

        result_arr.append(label[position])

    return result_arr


def report_ticket_id(filename):
    '''
    Function will iterate through the provided alarm filename and collect the
    incident ID values in that file.

            Returns: array of incident ID's.

            Parameter:
                filename: name of CSV file containing alarm related incident
                          ID's.
    '''

    result_arr = []

    with open(filename, encoding='utf8') as csv_file:
        csv_reader = csv.reader(csv_file)
        # Skip first row in the file
        next(csv_reader)
        for row in csv_reader:
            result_arr.append(row[0])

    return result_arr


def validation(predictions, arr, hexvals, filename):
    '''
    Function will create an output of the encoded hex code array (Hex Code),
    the correct classification (Actual) as an encoded array (length of output
    layer for learning model), predicition (Result), and boolean value
    determining if prediction was correct (Correctly Classified).

            Returns: (float) true value count over the total number of values
                     being predicted

            Parameters:
                predictions: list of values in the original ticket file
                arr: list of predicted values generated by learning model
                hexvals: hex value inputs that correlate to ticket file
                         incident ID's
                filename: resulting filename that will store results of this
                          function
    '''

    with open(filename, mode='w') as csv_file:
        fieldnames = ['Hex Code', 'Actual',
                      'Result', 'Correctly Classified']
        writer = csv.DictWriter(csv_file, fieldnames=fieldnames)

        writer.writeheader()

        # Converting np arrays to lists
        # predict_actual = np.array(predict_actual).tolist()
        predict_actual = np.array(predictions).tolist()
        arr = np.array(arr).tolist()

        length_of_array = len(hexvals)
        num_of_vals = len(predict_actual[0])
        true_counter = 0

        # loops through rows
        for rows in range(length_of_array):
            greatest_percent = max(arr[rows])
            boolean = False
            position = 0

            # gets the index of largest confidence value
            for index in range(num_of_vals):
                if arr[rows][index] == greatest_percent:
                    position = index

            # if the index of largest confidence value equals the index of
            # actual classification
            for index in range(num_of_vals):
                if predict_actual[rows][index] == 1 and index == position:
                    boolean = True
                    true_counter += 1

            writer.writerow({'Hex Code': hexvals[rows],
                             'Actual': predict_actual[rows],
                             'Result': arr[rows],
                             'Correctly Classified': boolean})
        csv_file.close()

    return true_counter / length_of_array
