#!/usr/bin/python

# ****************************************
# +++  BioCASE 
# +++  CMF Updater   
#
# Updates all CMFs to the latest version.
# Keeps the old files renamed in its directory.
#
# ****************************************


# ***** include the biocase.lib directory in the python sys path for importing *****
import os, sys
execfile( os.path.abspath(os.path.join(os.path.dirname( __file__ ), os.path.pardir, 'lib', 'biocase', 'adjustpath.py' ) ) )

# other imports
from biocase.wrapper.cmf_base import CMFClass
from biocase.wrapper.static_functions import getAbsoluteCWDirectory
from biocase.wrapper.cmf_handler import CMFVersionHandler
from biocase.configuration import Cfg
import traceback
from os.path import join, getsize


#
# functions
#
def updateCMF(fn, latestCMF):
	'''rename old CMF file and write the updated CMF with the old filename.'''
	print "-"*20
	print "CMF found for updating:"
	print "\t" +fn
	CMFObject    = CMFClass()
	versionTuple = CMFObject.__getCMFversion__(fn)
	newfn        = getNewFilename(fn, versionTuple[0])
	print "\tversion "+versionTuple[0]
	if latestCMF[1] == versionTuple[1]:
		print "\tAlready up to date. No changes done."
	else:
		try:
			os.rename(fn, newfn)
			print "\tRenamed existing file to: "
			print "\t"+newfn
			CMFObject.loadCMFdata(newfn)
			CMFObject.writeCMF(fn, latestCMF[1])
			print "\tupdated."
			os.remove(newfn)
			print "\tremoved serialized object for this CMF."
		except:
			print "\tFAILED !"
			error = sys.exc_info()
			errorMsg = "".join( traceback.format_exception( error[0], error[1], error[2] ) )
			print errorMsg
			try:
				os.rename(newfn, fn)
				print "\tRenamed existing file back to its original name."
			except:
				pass
        

def getNewFilename(fn, version):
	'''create new filename that does not exist already.'''
	newfn = fn[:-4] + '_v'+version+'-OLD.xml'
	i = 1
	while os.path.isfile(newfn):
		newfn = fn[:-4] +'_'+str(i) +'_v'+version +'-OLD.xml'
		i+=1
	return newfn
	

def updateCMFs(updateDir, CMFVersionTuple):
	print "-"*40
	print "Updating CMFs in dir=%s to version %s ..." %( updateDir, CMFVersionTuple[0] )
	print
	# get list of files
	cmfs=[]
	pickles=[]
	for root, dirs, files in os.walk(updateDir):
		for fn in files:
			absfn = os.path.join(root, fn)
			if len(fn) > 8 and fn[:4]=='cmf_' and fn[-4:]=='.xml' and fn[-8:]!='-OLD.xml':
				cmfs.append(absfn)
			elif len(fn) > 8 and fn[:5]=='.cmf_' and (fn[-5:]=='.pick' or fn[-7:]=='.pickle'):
				pickles.append(absfn)
	# remove pickles
	for absfn in pickles:
		try:
			print "-"*20
			print "Remove serialized CMF object: "
			print "\t" +absfn
			os.remove(absfn)
		except:
			print "Error !!!"
			error = sys.exc_info()
			errorMsg = "".join( traceback.format_exception( error[0], error[1], error[2] ) )
			print errorMsg
	# update CMFs
	for absfn in cmfs:
		try:
			updateCMF(absfn, CMFVersionTuple)
		except:
			print "Error !!!"
			error = sys.exc_info()
			errorMsg = "".join( traceback.format_exception( error[0], error[1], error[2] ) )
			print errorMsg
	
	

############################################################################################################
#
# MAIN
#
#===========================================================================================================

if __name__ ==  "__main__":

	cfg = Cfg()
	latestCMF = CMFVersionHandler()._NS2InfoTuple(CMFClass.CMFnamespace[-1]) # latest CMF version
	
	# latestCMF = CMFVersionHandler()._NS2InfoTuple(CMFClass.CMFnamespace[2])    # for version 2.1
	# latestCMF = CMFVersionHandler()._NS2InfoTuple(CMFClass.CMFnamespace[1])    # for version 2.0
	# latestCMF = CMFVersionHandler()._NS2InfoTuple(CMFClass.CMFnamespace[0])    # for version 1.4

	print "+++ BioCASE"
	print "+++ CMF Updater v1.0"
	print
	print "This software scans your provider software installation or any"
	print "other directories for CMFs to convert them into different CMF versions."
	print
	print "The latest available CMF version is " +latestCMF[0]
	print
	print

	# GET RECURSIVE UPDATE DIRECTORY
	defaultDir = cfg.datasourcesLocator
	updateDir  = ""
	print "The root directory to recursively search for CMFs to be updated:"
	while len(updateDir)<2:
		updateDir = raw_input("( default=%s ) : "%defaultDir)
		if len(updateDir) < 2:
			updateDir = defaultDir
		if not os.path.isdir(updateDir):
			print "This directory does not exist! Try again."
			updateDir = ""
	# GET CMF VERSION TO UPDATE TO
	print
	print "Available CMF versions:"
	SelectedVersion  = -1
	NSreversed = list(CMFClass.CMFnamespace)
	NSreversed.reverse()
	i = -1
	for NS in NSreversed:
		i += 1
		print "   %i - version %s" %( i, CMFVersionHandler()._NS2InfoTuple(NS)[0] )
	while not(SelectedVersion <= i and SelectedVersion >= 0):
		try:
			UserInput = raw_input("Select the CMF version to update to (default=0) : ")
			if len(UserInput) == 0:
				# use the default version
				SelectedVersion = 0
			else:				
				SelectedVersion = int(UserInput)
		except:
			SelectedVersion = -1
	CMFVersionTuple = CMFVersionHandler()._NS2InfoTuple(NSreversed[SelectedVersion])
	#
	# START WORK !
	#
	updateCMFs(updateDir, CMFVersionTuple)
	# end
	print
	print "Finished."
	