#!/usr/bin/env python3

# Note: this utility can run under python2.7 or python3

from getopt import getopt
from sys import stdout, argv, exit
from os.path import isfile, isdir
from os import getcwd, system

program = 'difxcopy'
version = '0.6'
author  = 'Walter Brisken'
verdate = '20210505'

fileTypes = ['input', 'calc', 'flag', 'machines', 'threads']

def usage(prog):
	prefixes = ''
	for f in fileTypes:
		prefixes = prefixes + f + ' '
	print('\n%s ver. %s  %s %s' % (program, version, author, verdate))
	print('\nA program to copy DiFX input (and other) files to a different directory,\nproperly modifying the path of references to other files in the process.\nThis program is typically run by difxqueue.')
	print('\nUsage: %s [options] <jobPrefix1> [<jobPrefix2> [ ... ] ] <destDirectory>\n' % prog)
	print('options can include\n')
	print('  --help')
	print('  -h         print this help information and quit\n')
	print('  --verbose')
	print('  -v         be more verbose in operation\n')
	print('jobPrefixN is the prefix of a job name, e.g., mt911_03 would be\n  the prefix for files mt911_03.input and mt911_03.calc.\n')
	print('destDir is the destination directory for the copy.\n')
	print('\nFiles with the following suffixes will be copied:')
	print('  %s\n' % prefixes)
	exit(0)

def outstring(k, v):
	key = k + ':'
	return '%-20s%s' % (key, v)
			
def handleVex(pathName, destination, verbose, vexFiles):
	pair = [pathName, destination]
	if not pair in vexFiles:
		vexFiles.append(pair)
		cmd = 'cp %s %s' % (pathName, destination)
		if verbose:
			print('Vex copy %s --> %s\n' % (pathName, destination))
		system(cmd)
	else:
		if verbose > 1:
			print('Not copying vex file %s to %s more than once\n' % (pathName, destination))

def copyfile(pathName, destination, listOfFiles, verbose, vexFiles):
	if destination[-1] == '/':
		dest = destination
	else:
		dest = destination + '/'
	fileName = dest + pathName.split('/')[-1]
	
	if pathName in listOfFiles:
		return []
	else:
		listOfFiles.append(pathName)

	if isdir(pathName):
		if verbose:
			print('Skipping %s as it is a directory.' % pathName)
		return []
	
	if not isfile(pathName):
		if verbose:
			print('File %s not found.  Skipping.' % pathName)
		return []

	if verbose:
		print('%s --> %s' % (pathName, fileName))

	indatalines = open(pathName, 'r').readlines()
	out = open(fileName, 'w')
	changedFiles = []
	indatatable = False
	for indata in indatalines:
		colonPos = indata.find(':')
		if len(indata) < 21:
			outdata = indata
		elif colonPos < 1:
			outdata = indata
		elif indata[0:5] == 'FILE ' and indatatable:
			outdata = indata
		elif indata[0] == '@':
			outdata = indata
		elif indata[0:12] == 'DATA FORMAT:':
			outdata = indata
		else:
			fn = indata[colonPos+1:].strip()
			s = fn.split('/')
			if len(s) == 1 or fn[0] != '/' or indata.split(':')[0] == 'DATA FORMAT':
				outdata = indata
			else:
				outdata = outstring(indata[:colonPos], dest + s[-1]) + '\n'
				changedFiles.append(fn)
		if verbose > 1 and indata != outdata:
			stdout.write('   <--  %s' % indata)
			stdout.write('    --> %s' % outdata)
		out.write(outdata)
		if len(indata.split()) > 2 and indata.split()[0] == 'D/STREAM' \
		   and indata.split()[2] == 'FILES:':
			indatatable = True
	out.close()

	if verbose:
		print('')

	for f in changedFiles:
		pathName = f
		if pathName[0] != '/':
			pathName = getcwd()+'/'+pathName
		if len(pathName) > 4 and pathName[-4:] == '.vex':
			handleVex(pathName, destination, verbose, vexFiles)
		else:
			copyfile(pathName, destination, listOfFiles, verbose, vexFiles)

def copyfiles(jobPrefix, destination, verbose, vexFiles):
	j = jobPrefix.split()[-1]
	listOfFiles = []
	for f in fileTypes:
		pathName = jobPrefix + '.' + f
		if pathName[0] != '/':
			pathName = getcwd()+'/'+pathName
		if isfile(pathName) and pathName not in listOfFiles:
			copyfile(pathName, destination, listOfFiles, verbose, vexFiles)

prefixes = []
verbose = 0
for a in argv[1:]:
	if a[0] == '-':
		if a in ['-h', '--help']:
			usage(argv[0])
		if a in ['-v', '--verbose']:
			verbose += 1
	else:
		if a[-6:] == '.input':
			jobPrefix = a[:-6]
		else:
			jobPrefix = a
		prefixes.append(jobPrefix)

if len(prefixes) < 2:
	usage(argv[0])

destination = prefixes[-1]
prefixes = prefixes[:-1]
vexFiles = []

for p in prefixes:
	if not isfile(p) and not isfile(p+'.input'):
		print('No job named %s found here.  Continuing anyway.' % p)
	else:
		copyfiles(p, destination, verbose, vexFiles)
