#!/usr/bin/env python3

import os
import sys
import csv
import fileinput
import subprocess

def parse_onionperf_file(file_name):
    res = {}
    # fetch sources
    sources = fetch_sources(file_name)

    # collect circuit building times for source
    for s in sources:
        with open(os.path.dirname(__file__) + "/datasets/" + file_name, 'r') as f:
            reader = csv.DictReader(filter(lambda row: row[0]!='#', f), delimiter=',')
            s_counter = 0
            s_total = 0
            for row in reader:
                if row['source'] == s:
                    # we have completed a circuit after reaching the exit relay
                    if int(row['position']) == 3:
                        s_counter += 1
                    s_total += float(row['md'])

            # calculate average
            if s_counter != 0:
                res[s] = s_total/s_counter

    return res

def fetch_sources(file_name):
    sources = []

    with open(os.path.dirname(__file__) + "/datasets/" + file_name, 'r') as f:
        # open the file rows as dicts, skip the comments
        reader = csv.DictReader(filter(lambda row: row[0]!='#', f), delimiter=',')
        # fetch sources
        for row in reader:
            if row['source'] != '' and row['source'] not in sources:
                sources.append(row['source'])
        f.close()

    return sources


# Plot the relative circuit building times using gnuplot
if __name__ == '__main__':
    # set some defaults
    file_name = os.getenv('CB_FILE')

    # fetch average times from onion performance file
    avg_times = parse_onionperf_file(file_name)

    #print(avg_times)

    # fetch simulator times
    sim_times = {}
    dats = []
    dats += [each for each in os.listdir('.') if each.endswith('.dat') and 'client_c_relative' not in each]

    for dat in dats:
        with open(dat, 'r') as f:
            for line in f.readlines():
                sim_times.update({dat: float(line.split(" ")[15])})

    #print(sim_times)

    # vanilla is base
    base = sim_times['vanilla_none.dat']

    # calculate ratios
    ratios = {
        'tele-thresh': sim_times['telescoping_threshsig.dat']/base,
        'tele-merkle': sim_times['telescoping_merkle.dat']/base,
        'singlep-thresh': sim_times['singlepass_threshsig.dat']/base,
        'singlep-merkle': sim_times['singlepass_merkle.dat']/base
    }

    #print(ratios)

    # calculate relative times
    relative_times = {}

    for avg in avg_times.keys():
        for ratio in ratios.keys():
            relative_times.update({
                avg + "-vanilla": avg_times[avg]
            })
            relative_times.update({
                avg + "-" + ratio: avg_times[avg] * ratios[ratio]
            })

    #print(relative_times)

    # Create dat file
    for source in fetch_sources(file_name):
        with open("client_c_relative-%s.dat" % source, "w") as datout:
            for k in relative_times.keys():
                if source in k:
                    datout.write("%s " % \
                            (relative_times[k]))
            datout.close()

    # Build plot
    for source in fetch_sources(file_name):
        output_file = "client_c_relative-%s.pdf" % source
        gpcode = """set terminal pdf font "DejaVuSans,14" size 5,2.25
        set output '%s'
        set title 'Relative circuit building times'
        set arrow from %s
        set grid y
        set key out
        unset xtics
        set ylabel 'Relative times (ms)'
        plot """ % (output_file, max(relative_times.values()))

        col = 1
        firstplot = True

        for k in relative_times.keys():
            if source in k and source:
                if firstplot is False:
                    gpcode += ", "
                gpcode += "'client_c_relative-%s.dat' using 0:%d with points title '%s'" % (source, col, k)
                col += 1
                firstplot = False


        gp = subprocess.Popen(['gnuplot', '-'], stdin=subprocess.PIPE)
        gp.communicate(gpcode.encode('ascii'))
