#!/usr/bin/env python

"""
# setup once
./barter-ec-generator.py 10
./barter-setup-environment.sh 10

# obtain stats to plot
./barter-cluster-run

# parse logs and plot
./barter-generate-graphs peers_directory | gnuplot

# loot at graphs
display peers/records.png
"""

from time import mktime
import re
from os import listdir, path
from ldecoder import parse
from sys import argv
import os.path
import os
import sys

node_count = 0

def get_nodes(peer_dir):
    global node_count
    pattern = re.compile('[0-9]{5}')
    for d in listdir(peer_dir):
        if pattern.match(d):
            
            dispersy_exists = os.path.exists(os.path.join(peer_dir, d, 'output','dispersy.log'))
            if int(d) <= node_count and dispersy_exists:
                yield peer_dir + "/" + d

def get_title(node):
    if re.match(".*[0-9]{5}", node):
        return node[-5:]
    elif len(node)>7 and node[-7:] == "tracker":
        return "tracker"
    return "???"

def plot_received_records(peers_directory, first, last):
    """ I plot the received records per peer"""
    print "set ylabel 'number of records received'"
    # print "set yrange [%d:%d]" % (0, 500)
    print "set xrange [%d:%d]" % (0, last - first)
    #print "set key bottom right" #MB
    print "plot",
    first = True
    for node in get_nodes(peers_directory):
        if first:
            first = False
        else:
            print ", \\\n    ",

        filename = node + "/output/received-record.txt"
        print "'%s'" % filename,
        print "using 2:3",
        print "title '%s'" % get_title(node),
        print "with steps",

    print ""

def plot_total_records(peers_directory, first, last):
    """ I plot the total (received, created) records per peer """
    print "set ylabel 'number of records per peer'"
    # print "set yrange [%d:%d]" % (0, 1500)
    print "set xrange [%d:%d]" % (0, last - first)
    print "plot",
    first = True
    for node in get_nodes(peers_directory):
        if first:
            first = False
        else:
            print ", \\\n    ",

        filename = node + "/output/total-record.txt"
        print "'%s'" % filename,
        print "using 2:3",
        print "title '%s'" % get_title(node),
        print "with steps",

    print ", \\\n    ",
    print "'"+ peers_directory + "/output/sum_created_records.txt'",
    print "using 1:2",
    print "title 'total'",
    print "with steps lw 2",
    print ""

def plot_drop(peers_directory, first, last):
    """ I plot the dropped records per peer """
    print "set ylabel 'number of records droped'"
    # print "set yrange [%d:%d]" % (0, 500)
    print "set xrange [%d:%d]" % (0, last - first)
    print "plot",
    first = True
    for node in get_nodes(peers_directory):
        if first:
            first = False
        else:
            print ", \\\n    ",

        filename = node + "/output/drop.txt"
        print "'%s'" % filename,
        print "using 2:3",
        print "title '%s'" % get_title(node),
        print "with steps",

    print ""

def plot_send(peers_directory, first, last):
    """ I plot the kilobytes send per peer """
    print "set ylabel 'number of kilobytes send'"
    print "set xrange [%d:%d]" % (0, last - first)
    print "plot",
    first = True
    for node in get_nodes(peers_directory):
        if first:
            first = False
        else:
            print ", \\\n    ",

        filename = node + "/output/stat.txt"
        print "'%s'" % filename,
        print "using 2:($3/1024)",
        print "title '%s'" % get_title(node),
        print "with steps",
    print ""

def plot_received(peers_directory, first, last):
    """ I plot the kilobytes received per peer """
    print "set ylabel 'number of kilobytes received'"
    print "set xrange [%d:%d]" % (0, last - first)
    print "plot",
    first = True
    for node in get_nodes(peers_directory):
        if first:
            first = False
        else:
            print ", \\\n    ",

        filename = node + "/output/stat.txt"
        print "'%s'" % filename,
        print "using 2:($4/1024)",
        print "title '%s'" % get_title(node),
        print "with steps",
    print ""
    
def plot_statistics(peers_directory, first, last):
    print "set ylabel 'sum of statistic'"
    print "set xrange [%d-%d]" % (0, last - first)
    
    
def write_stat(outputfile, averagefile, peers_directory, column):
    print >> outputfile, '#timeoffset, kb diff+'

    node_dict = {}
    node_max = {}
    timeoffsets = set()

    for node in get_nodes(peers_directory):
        stat = open(node + "/output/stat.txt", 'r')
        
        _, node_name = os.path.split(node)

        for line in stat.readlines():
            if not line.startswith('#'):
                columns = line.split()
                if len(columns) == 4:
                    timeoffsets.add(int(columns[1]))
                    
                    if node_name not in node_dict:
                        node_dict[node_name] = {}
                    node_dict[node_name][int(columns[1])] = int(columns[column])
                    node_max[node_name] = max(node_max.get(node_name, 0), int(columns[column]))

    def intsort(a, b):
        return cmp(int(a), int(b))

    peer_names = node_dict.keys()
    peer_names.sort(cmp = intsort)
    print >> outputfile, ' '.join(peer_names)
    print >> averagefile, ' '.join(peer_names)

    timeoffsets = list(timeoffsets)
    timeoffsets.sort(cmp = intsort)

    prev_values = {}

    for timeoffset in timeoffsets:
        print >> outputfile, timeoffset, 

        for peer in peer_names: 
            prev_value = prev_values.get(peer, 0)
            cur_value = int(node_dict[peer].get(timeoffset, prev_value))
            diff = (cur_value - prev_value)/1024.0
            
            if diff == 0:
                print >> outputfile, '?',                 
            else:
                print >> outputfile, diff,
            prev_values[peer] = cur_value

        print >> outputfile, ''
    
    max_time = float(max(timeoffsets))
    
    for peer in peer_names:
        print >> sys.stderr, peer, node_max[peer], max_time
        print >> averagefile, (int(node_max[peer])/max_time)/1024.0, 

def header(peers_directory, filename):
    print "reset"
    print "set terminal postscript eps enhanced color \"Helvetica\" 16 solid"
    print "set output '"+ peers_directory + "/output/%s.eps'" % filename
    print "set xlabel 'Time expired in seconds'"
    print "unset key"

def records(peers_directory, first, last):
    header(peers_directory, "records-total")
    plot_total_records(peers_directory, first, last)

def received_records(peers_directory, first, last):
    header(peers_directory, "records-received")
    plot_received_records(peers_directory, first, last)

def drops(peers_directory, first, last):
    header(peers_directory, "records-dropped")
    plot_drop(peers_directory, first, last)

def received(peers_directory, first, last):
    header(peers_directory, "traffic-received")
    plot_received(peers_directory, first, last)

def sent(peers_directory, first, last):
    header(peers_directory, "traffic-sent")
    plot_send(peers_directory, first, last)

def multiplot(peers_directory, first, last):
    header(peers_directory, "multiplot")
    print "set grid"
    print "set size 1,1"
    print "set origin 0,0"
    print "set multiplot layout 2,2 rowsfirst "

    # print "set multiplot"
    # print "set size 0.5, 0.5"
    # print "set origin 0.0, 0.5" # upper left
    # plot_received_record(first, last)
    plot_total_records(peers_directory, first, last)
    # print "set origin 0.5, 0.5" # upper right
    plot_drop(peers_directory, first, last)
    # print "set origin 0.0, 0.0" # lower left
    plot_received(peers_directory, first, last)
    # print "set origin 0.5, 0.0" # lower right
    plot_send(peers_directory, first, last)
    print "unset multiplot"

def main(peers_directory):
    global node_count
    peer_count = open(peers_directory+'/peer.count', 'r')
    node_count = int(peer_count.readline())
    peer_count.close()
    
    fn_first_last = peers_directory + "/output/first_last.txt"
    h_first_last = open(fn_first_last, "r")
    [ first, last ] = [int(i) for i in h_first_last.readline().strip().split()]
    h_first_last.close()
 
    for func in [records, drops, received, sent, received_records]:
        func(peers_directory, first, last+100)
        
    received_f = open(peers_directory + "/output/received.txt", "w")
    avg_received_f = open(peers_directory + "/output/avgreceived.txt", "w")
    write_stat(received_f, avg_received_f, peers_directory, 3)
    avg_received_f.close()
    received_f.close()

    send_f = open(peers_directory + "/output/send.txt", "w")
    avg_send_f = open(peers_directory + "/output/avgsend.txt", "w")
    write_stat(send_f, avg_send_f, peers_directory, 2)
    avg_send_f.close()
    send_f.close()

if __name__ == "__main__":
    main(argv[1])
