#!/usr/bin/env python
# -*- coding: utf-8 -*-

from collections import defaultdict
from glob import glob
import argparse
import fnmatch
import itertools
import os
import re
import sys

def is_file(path):
  return os.path.isfile(path) and not os.path.isdir(path)

def is_dir(path):
  return os.path.isdir(path)

TEST_REGEX=re.compile("^(?P<arch>PPC|ARM8|X86) (?P<name>test_[0-9a-f]*)$")
WITNESS_REGEX=re.compile("^Positive: (?P<pos>[0-9]+), Negative: (?P<neg>[0-9]+)$")
def parse_log(path):
  tests, pos, neg = [], [], []
  with open(path) as f:
    for line in f:
      m = TEST_REGEX.match(line)
      if m: tests.append(m.group("name"))
      m = WITNESS_REGEX.match(line)
      if m:
        pos.append(int(m.group("pos")))
        neg.append(int(m.group("neg")))
  assert len(tests) == len(pos)
  assert len(tests) == len(neg)
  results = {}
  for t,p,n in itertools.izip(tests, pos, neg):
    assert t not in results
    results[t] = (p,n)
  return results

NEVENTS = re.compile('(?P<nevents>\d+)ev')
def nevents(path):
  m = NEVENTS.search(path)
  return int(m.group('nevents'))

MACHINE = re.compile('result_(?P<machine>[^.]+)\.log')
def machine(path):
  m = MACHINE.search(path)
  return m.group('machine')

def arch(path):
  if "X86" in path: return "X86"
  elif "PPC" in path: return "PPC"
  else: assert False

def fences(path):
  if "fences-as-nodes" in path: return "nodes"
  elif "fences-as-edges" in path: return "edges"
  else: assert False

def allow_forbid_set(path):
  if "allow" in path: return "allow"
  else: return "forbid"

def split_path(path):
  n = nevents(path)
  s = allow_forbid_set(path)
  m = machine(path)
  a = arch(path)
  f = fences(path)
  return n,s,m,a,f

def litmus_stats(test):
  if arch(test) == "X86": sentinel = "XBEGIN"
  elif arch(test) == "PPC": sentinel = "tbegin"
  ntransactions, nthreads = 0, None
  with open(test) as f:
    for line in f:
      ntransactions += line.count(sentinel)
      if line.startswith("P0"):
        nthreads = len(line.split("|"))
  return ntransactions, nthreads

def find_all(path, pattern):
  for root, dirnames, filenames in os.walk(path):
    for filename in fnmatch.filter(filenames, pattern):
      yield os.path.abspath(os.path.join(root, filename))

def is_existing_dir(arg):
  if os.path.isdir(arg):
    return os.path.abspath(arg)
  raise argparse.ArgumentParser("Result directory does not exist [%s]" % arg)

def main(argv=None):
  parser = argparse.ArgumentParser(description="log2csv")
  parser.add_argument("result_dir", type=is_existing_dir)
  args = parser.parse_args(argv)
  print "nevents,testset,machine,arch,fences,test,pos,neg,ntxs,nthreads"
  for log in find_all(args.result_dir, "result_*.log"):
    n,s,m,a,f = split_path(log)
    results = parse_log(log)
    base = os.path.dirname(log)
    for t in results:
      pos,neg = results[t]
      litmus = os.path.join(base,"%s.litmus" % t)
      ntx, nthd = litmus_stats(litmus)
      print "%d,%s,%s,%s,%s,%s,%d,%d,%d,%d" % (n,s,m,a,f,t,pos,neg,ntx,nthd)
  return 0

if __name__ == '__main__':
  sys.exit(main())
