#!/usr/bin/env python3

import os
import re
import subprocess
import sys

def run_bench(cmd):
    """Run the benchmark with the given command (passed as an array of
    arguments).  The benchmark is expected to output on stdout one or more
    csv tables, of the form:

    === Table 5 ===

    protocol,request size,response size
    Open Invitation,249,543
    Trust Promotion,1677,2285
    Trust Migration,845,241
    Level Up,2253,241
    Issue Invite,1101,401
    Redeem Invite,1037,241
    Check Blockage,685,325
    Blockage Migration,973,241
    Update Invite,557,209
    Update Credential,749,209
    
    This function will return a dictionary with keys being the name of the
    table ("Table 5"), and the value being a list of csv rows, where each row
    is a dict with keys being the name of the column, and the value being the
    entry in that column."""
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True)
    table_name = None
    seen_nonempty_line = False
    retval = {}
    table = []
    headers = []
    for line in proc.stdout:
        print(line,end='')
        line = line.rstrip()
        if matched := re.match(r'=== (.*) ===', line):
            if table_name is not None:
                # Store the previous table
                retval[table_name] = table
            table_name = matched.group(1)
            seen_nonempty_line = False
            table = []
            headers = []
            continue
        if line == "" and seen_nonempty_line == True:
            if table_name is not None:
                # The table is finished; store it
                retval[table_name] = table
                table_name = None
                seen_nonempty_line = False
                table = []
                headers = []
            continue
        if line == "":
            continue
        # At this point, we know the line is nonempty
        if len(headers) == 0:
            # This should be the header line
            headers = line.split(',')
            seen_nonempty_line = True
        else:
            values = line.split(',')
            row = dict(zip(headers, values))
            table.append(row)

    # If stdout ends, and there's a table in progress, store it
    if table_name is not None:
        retval[table_name] = table

    return retval

os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])))
os.environ['PYTHONUNBUFFERED'] = '1'
if len(sys.argv) > 1:
    niters = sys.argv[1]
else:
    niters = "10"

lox_sigma_native = run_bench(["./run_native_bench", niters])
lox_zkp_native = run_bench(["./run_native_bench", "-z", niters])
lox_sigma_wasm = run_bench(["./run_wasm_bench", niters])
lox_zkp_wasm = run_bench(["./run_wasm_bench", "-z", niters])

print("\n*** Complete Table 2 ***\n")
print("protocol,zkp client native ms,zkp client wasm ms,zkp server native ms,sigma-rs client native ms,sigma-rs client wasm ms,sigma-rs server native ms")
for r in range(len(lox_sigma_native['Table 2'])):
    proto = lox_sigma_native['Table 2'][r]['protocol']
    assert proto == lox_zkp_native['Table 2'][r]['protocol']
    assert proto == lox_sigma_wasm['Table 2'][r]['protocol']
    assert proto == lox_zkp_wasm['Table 2'][r]['protocol']
    print(','.join([
        proto,
        lox_zkp_native['Table 2'][r]['client native ms'],
        lox_zkp_wasm['Table 2'][r]['client wasm ms'],
        lox_zkp_native['Table 2'][r]['server native ms'],
        lox_sigma_native['Table 2'][r]['client native ms'],
        lox_sigma_wasm['Table 2'][r]['client wasm ms'],
        lox_sigma_native['Table 2'][r]['server native ms'],
    ]))

print("\n*** Complete Table 5 ***\n")
print("protocol,zkp request bytes,zkp response bytes,sigma-rs request bytes,sigma-rs response bytes")
for r in range(len(lox_sigma_native['Table 5'])):
    proto = lox_sigma_native['Table 5'][r]['protocol']
    assert proto == lox_zkp_native['Table 5'][r]['protocol']
    print(','.join([
        proto,
        lox_zkp_native['Table 5'][r]['request size'],
        lox_zkp_native['Table 5'][r]['response size'],
        lox_sigma_native['Table 5'][r]['request size'],
        lox_sigma_native['Table 5'][r]['response size'],
    ]))
