import glob, os
import pandas as pd

def get_features(video_path, feature_extraction_exe):
    """
    Extracts OpenFace features from a video file.
    
    Parameters:
        video_path (String): path to the video (includes the video within the path)
        feature_extraction_exe (String): path to FeatureExtraction executable within OpenFace. Format should be
            "path_to_OpenFace/build/bin/FeatureExtraction"
    """
    os.system(feature_extraction_exe + ' -f "' + video_path + '"')

def reformat_data(video_name, directory, human_readable = False):
    """
    Reformats the CSV output of OpenFace FeatureExtraction into the PsychDS format. Creates a CSV file,
    named [video name]_openface_data.csv, with the newly reformatted data in the parent directory of the video.
    
    Parameters:
        video_name (String): name of the video (not including type of file)
        directory (String): path to directory to put the reformatted data in
        human_readable (bool):
            True if should output reformatted file in a human_readable format (i.e. each row reflects a
                change in the trackname)
            False otherwise (i.e. for comparing purposes as in the compare_data function)
    """
    #path to directory that holds output of running OpenFace
    processed_directory = os.path.dirname(os.path.realpath(__file__)) + '/processed/'
    
    #finds csv output from running OpenFace
    data = pd.read_csv(processed_directory + video_name + ".csv", engine='python', delimiter = ', ')   
    #forms DataFrame in desired output format
    reformatted_data = pd.DataFrame(columns=['Time', 'Duration', 'Trackname', 'Comments'])
    #for human_readable = True
    reformatted_index = 0
    
    for index, row in data.iterrows():
        horizontal_gaze_angle = row['gaze_angle_x']
        if row['success'] == 0:
            trackname = 'off'
        elif row['gaze_0_x'] < row['gaze_1_x']:
            trackname = 'away'
        elif horizontal_gaze_angle >= 0.22:
            trackname = 'left'
        else:
            trackname = 'right'
        
        if human_readable:
            if reformatted_index == 0 or reformatted_data.loc[reformatted_index - 1]['Trackname'] != trackname:
                reformatted_data.loc[reformatted_index] = [row['timestamp'], 0, trackname, '(null)']
                reformatted_index += 1
        else:
            reformatted_data.loc[index] = [row['timestamp'], 0, trackname, '(null)']
    
    reformatted_data.to_csv(directory + video_name + '_openface_data.tsv', index=False, sep='\t')
    
def compare_data(original_tsv_path, new_tsv_path):
    """
    Compares data in one TSV file to another, and finds accuracy of that TSV file.
    
    Assumes that the TSV file in the original_tsv_path is in the format generated by Khaled's script
    when converting from a Marchman VCX file to a TSV file.
    
    Parameters:
        original_tsv_path (String): path to the TSV file containing the original hand-coded data 
            (i.e. the standard being comparing to). Assumes that it is in the Lookit format (i.e. the 
            format generated by using Khaled's script on the Marchman data).
        new_tsv_path (String): path to the TSV file containing the new data (i.e. the data trying to find 
            accuracy of). Should be in the PsychDS format. This the generated TSV file from the reformat_data 
            function.
    
    Returns:
        float: accuracy of data in the new CSV file when compared to the original CSV file
    """
    original_df = pd.read_csv(original_tsv_path, engine='python', delimiter = '\t')
    new_df = pd.read_csv(new_tsv_path, engine='python', delimiter = '\t')

    new_idx = 0 #to keep track of index within new_tsv
    num_correct = 0
    count = 0
    
    for orig_idx in range(len(original_df)-1): #don't want last entry because signifies end
        while new_idx < len(new_df) and new_df.iloc[new_idx]['Time'] < original_df.iloc[orig_idx]['Time']/1000:
            new_idx += 1
        if abs(new_df.iloc[new_idx]['Time'] - original_df.iloc[orig_idx]['Time']/1000) > abs(new_df.iloc[new_idx-1]['Time'] - original_df.iloc[orig_idx]['Time']/1000):
            temp_idx = new_idx - 1
        else:
            temp_idx = new_idx
        
        #to keep track of the accuracy of the new data
        if new_df.iloc[temp_idx]['Trackname'] == original_df.iloc[orig_idx]['Trackname']:
            num_correct += 1
        count += 1
 
    return num_correct/count

def combine_data(path, train_num):
    """
    Merges the gaze data files so that train_num number of files are merged into train.tsv, and the rest are
    merged into test.tsv.
    
    Parameters:
        path (String): path to the folder containing all the gaze data files.
        train_num (int): number of data files to concatenate into train.tsv. The rest goes into test.tsv.
    """
    all_files = glob.glob(os.path.join(path, "*.tsv"))
    
    train_df = (pd.read_csv(all_files[i], sep='\t') for i in range(train_num))
    train_df = pd.concat(train_df, ignore_index=True)
    test_df = (pd.read_csv(all_files[i], sep='\t') for i in range(train_num, len(all_files)))
    test_df = pd.concat(test_df, ignore_index=True)
    
    train_df.to_csv(path + 'train.tsv', index=False, sep='\t')
    test_df.to_csv(path + 'test.tsv', index=False, sep='\t')
