###############################################################################
#                                                                             #
#   Copyright 2005 University of Cambridge Computer Laboratory.               #
#                                                                             #
#   This file is part of Nprobe.                                              #
#                                                                             #
#   Nprobe is free software; you can redistribute it and/or modify            #
#   it under the terms of the GNU General Public License as published by      #
#   the Free Software Foundation; either version 2 of the License, or         #
#   (at your option) any later version.                                       #
#                                                                             #
#   Nprobe is distributed in the hope that it will be useful,                 #
#   but WITHOUT ANY WARRANTY; without even the implied warranty of            #
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             #
#   GNU General Public License for more details.                              #
#                                                                             #
#   You should have received a copy of the GNU General Public License         #
#   along with Nprobe; if not, write to the Free Software                     #
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA #
#                                                                             #
###############################################################################


#
# Some basic utility functions for manipulating Nprobe logs and generic records
#

import string
import glob
import os
import sys
from sys import argv

from nprobe import np_file, counters


############################################################################

class EOF_REACHED:
    def __init__(self, file):
	self.file = file



#############################################################################

#
# Compare two Nprobe us_clocks 
# - return 1 if first later, -1 if first earlier, 0 if same
#

def cmp_us_clk(a, b):
	if a.us_high > b.us_high:
		return 1
	elif a.us_high < b.us_high:
		return -1
	else:
		if a.us_low > b.us_low:
			return 1
		elif a.us_low < b.us_low:
			return -1
		else:
			return 0
	
#############################################################################
		

#check sorted list of rep files is contiguous
def contig(l):
	tup = l[0]
	first = tup[1]

	for i in range(1, len(l)):
		tup = l[i]
		second = tup[1]
		if first + 1 != second:
			print "# WARNING -  rep file discontinuity ",
			print tup[0]
			first = second
			second = second + 1
			#sys.exit(1)
		else:
			first = second

############################################################################# 

#sort cmp function for list of rep files
def cmp_fileseq(a, b):
	if a[1] > b[1]:
		return 1
	elif a[1] < b[1]:
		return -1
	else:
		return -1
		print "ERROR - identical sequence numbers ",
		print a[0] + " " + b[0]
		sys.exit(1)

##############################################################################

#
# given a directory or file(s) create a list of rep file names representing 
# a continuous nprobe run - validate for type and continuity, 
# aggregate per - file counters.
# return (file name list, aggregated counters)
#

def get_files(args):

    # Possible channel prefixes
    chan_pref = 'AB'
    
    # Build list of files given in args
    dirname = ""
    filerange = ""
    filename = ""
    rawfilelist = []
    for name in args:
	#print name
	if os.path.isdir(name):
	    #print "is a dir"
	    dirlist =[]
	    print "# Files from " + name
	    dirname = name
	    #print dirname
	    for dname in os.listdir(name):
		#print dname
		rawfilelist.append(os.path.join(name, dname))
		
	else:
	    rawfilelist.append(name)

    #print rawfilelist

    # Build list of the rep files
    filenamelist = []

## Old channel naming scheme
 ##    for name in rawfilelist:
## 	if len(name) >= 12 and name[-10:-4] == "].rep." and name[-12] == "[":
## 	    repnum = string.atoi(name[-4:])
## 	    filenamelist.append((name, repnum))
 
    ## New channel naming scheme   
    for name in rawfilelist:
        
	if len(name) >= 10 and name[-9:-4] == ".rep." and chan_pref.count(name[-10]):
	    repnum = string.atoi(name[-4:])
	    filenamelist.append((name, repnum))

    if not len(filenamelist):
        nrf = len(rawfilelist)
        if nrf == 0:
            print 'No Nprobe rep file specified in c.l.'
            sys.exit(1)
        elif nrf == 1:
            print '%s is not an Nprobe rep file' % (rawfilelist[0])
            sys.exit(1)
        else:
            print 'No Nprobe rep files found amongst'
            for f in rawfilelist:
                print '\t%s' % (f)
            sys.exit(1)
            
    # Check contiguous cycles
    filenamelist.sort(cmp_fileseq)
    contig(filenamelist)

    #print filenamelist

    # Display files
    llen = len(filenamelist)
    if llen == 0:
	print "No files"
    elif len(filenamelist) == 1:
	name = filenamelist[0]
	#filename = os.path.split(name[0])[1]
	filename = name[0]
	#print filename
	print "# File ", os.path.split(name[0])[1]
    else:
	if not len(dirname):
	    dirname = os.path.split(filenamelist[0][0])[0]
	    filerange = os.path.split(filenamelist[0][0])[1]+"-"+os.path.split(filenamelist[llen - 1][0])[1]
	#print filerange
	print "# Files:", os.path.split(filenamelist[0][0])[1], " - ", os.path.split(filenamelist[llen - 1][0])[1] 
	print

    # Open files and build list
    openfilelist = []
    for name in filenamelist:
	a = np_file(name[0], 0)
	openfilelist.append(a)
    print "\n"

    # Accumulate counters over all cycles
    overallcounters = counters()

    for file in openfilelist:
	overallcounters.addin(file.counters)
	


 ##    for openfile in openfilelist:
## 	#openfile.printhdr()
## 	#openfile.printcounters()
	
## 	overallcounters.addin(openfile.counters)

    # Calculate base path for saved files

    if len(dirname) and not len(filerange):
	basepath = dirname + "/"
    elif len(filerange):
	if len(dirname):
	    basepath = dirname + "/" + filerange + "."
	else:
	    basepath = filerange + "."
    else:
	    basepath = filename + "."

    if basepath[-2:] == '//':
        basepath = basepath[:-1]
    elif basepath[-3:] == '/./':
        basepath = basepath[:-2]

    # Return list of open files and acuumulated counters
    return (openfilelist, overallcounters, basepath)

##############################################################################
		

# print entire tconn record

def print_conn_all(connrec, translist):
    connrec.printself()
    for trans in translist:
	trans.printself(connrec)
	
	return

#############################################################################

# Return type of next record - leave file position to read it
# as nprobe.next_rec but raises EOF_REACHED

def next_rec(file):
    res = file.next_rec()
    if res == -1:
	raise EOF_REACHED(file)
    else:
	return res

#############################################################################

# Seek to next record of specified type - return type

def next_type_rec(file, type):
    #print file.indx
    res = file.next_type_rec(type)
    if res == -1:
	raise EOF_REACHED(file)
    else:
	return res

#############################################################################

#
# Execute this on load to avoid nasty version bugs (and unsupported stuff)
#

V = string.split(string.split(sys.version)[0], '.')
if int(V[0]) < 2:
    print 'Interpreter is Python %s.%s\n ... Sorry must use 2.0 or above' \
          % (V[0], V[1])


