#!/usr/bin/env python

# python_bindings_unittest.py

# Copyright (C) 2005-2006 Visual Media FX Ltd.
# Released under the LGPL.
# For more information, see http://www.openlibraries.org.

import platform
import sys
import os.path
import shutil

if platform.system( ) == "Linux":
	import dl
	sys.setdlopenflags( dl.RTLD_NOW | dl.RTLD_GLOBAL )

import openpluginlib
import openimagelib
import openmedialib
import openassetlib as oal
import uuid				# http://home.arcor.de/jurner/python/uuid/dist/uuid-0.3.2.tar.gz

test_count = 0
pass_count = 0
fail_count = 0

###############################################
# define guid generator class acceptable to oal
class uuid_generator(oal.guid_generator):
	def generate_guid(self):
		return uuid.uuid_time()
	
#################################
def print_asset_content( asset ):
	print "\n\tGUID: ", asset.guid()
	if asset.size() == 0:
		print "\tContains no metadata"
	else:
		print "\t", asset.size(), " associated pieces of metadata"
		for metadata in asset:
			print "\t\t", metadata.first, "\t:\t", metadata.second

#############################
def print_set_content( set ):
	print "set name: \"%s\"" % set.name()
	if set.size() == 0:
		print "No Hits!"
	else:
		print "Got ", set.size(), " hits:"
		for a in set:
			print_asset_content(a)

##################################
def print_is_convertible( asset ):
	if oal.is_convertible(asset) == True:
		print "\nasset is convertible"
	else:
		print "\nasset isn't convertible"
		
#########################
def test_guid_bindings():
	global pass_count, fail_count
	guid1 = oal.create_guid()
	if guid1 is not None:
		pass_count = pass_count + 1
		print "\nguid1 = %s" % guid1.string()
	else:
		fail_count = fail_count + 1
	
	guid2 = oal.create_guid(str('{22222222-2222-2222-2222-222222222222}'))
	if guid2 is not None:
		pass_count = pass_count + 1
		print "\nguid2 = %s" % guid2.string()
	else:
		fail_count = fail_count + 1
		
	guid3 = oal.create_guid(0x2222222222222222, 0x2222222222222222)
	if guid3 is not None:
		pass_count = pass_count + 1
		print "\nguid3 = %s" % guid3.string()
		if guid2 == guid3:
			print "\nPASS: guid2 (%(1)s) == guid3 (%(1)s)" % {'1': guid2.string(), '2': guid3.string()}
			pass_count = pass_count + 1
		else:
			print "\nFAIL: guid2 (%(1)s) != guid3 (%(2)s)" % {'1': guid2.string(), '2': guid3.string()}
			fail_count = fail_count + 1
			
		if guid1 != guid2:
			print "\nPASS: guid1 (%(1)s) != guid2 (%(2)s)" % {'1': guid1.string(), '2': guid2.string()}
			pass_count = pass_count + 1
		else:
			print "\nFAIL: guid1 (%(1)s) == guid2 (%(2)s)" % {'1': guid1.string(), '2': guid2.string()}
			fail_count = fail_count + 1
			
		guid1 = guid2
		if guid1 == guid2:
			print "\nPASS: guid1 (%(1)s) == guid2 (%(2)s)" % {'1': guid1.string(), '2': guid2.string()}
			pass_count = pass_count + 1
		else:
			print "\nFAIL: guid1 (%(1)s) != guid2 (%(2)s)" % {'1': guid1.string(), '2': guid2.string()}
			fail_count = fail_count + 1
		
		
	else:
		fail_count = fail_count + 1
	
		
#
# Main method
#

def main( ):
	print 'Commencing exercise of openassetlib python bindings...'
	
	oal.init(uuid_generator())
	
	guid = oal.generate_guid()
	print 'generate_guid: %s' % guid.string()
	
	########################
	test_guid_bindings()
	
	########################
	print '\ncreating asset 1'
	asset1 = oal.create_asset()
	if asset1 is None:
		print '\tFailed'
	else:
		print '\tSucceeded'
	print_asset_content(asset1)
	
	print 'Changing the GUID...'
	print 'get_guid\t->\t', asset1.guid()
	#guid = oal.create_guid(str('{11111111-1111-1111-1111-111111111111}'))
	#asset1.guid(guid)
	#print 'set_guid\t<-\t', guid.string()
	#print 'get_guid\t->\t', asset1.guid()
	
	print "\tadding metadata..."
	asset1.set("a_bool", True)
	asset1.set("a_string", "Hello :-)")
	asset1.set("an_int", int(12345))
	asset1.set("a_long", long(1234567890))
	asset1.set("a_float", float(3.14159265))
	print_asset_content(asset1)
	
	print '\n\nFinding a_string metadata: %s\n\n' % asset1.find("a_string").second

	########################
	print '\nCreating asset 2 from asset1'
	asset2 = oal.create_asset(asset1)
	if asset2 is None:
		print '\tFailed'
	else:
		print '\tSucceeded'
	print_asset_content(asset2)
	
	print "\tmodifiying metadata & guid..."
	#asset2.guid(oal.create_guid(str('{22222222-2222-2222-2222-222222222222}')))
	asset2.set("a_bool", False)
	asset2.set("a_string", "I'm a number 2!")
	asset2.set("an_int", int(9876543210))
	asset2.set("a_long", long(98765))
	asset2.set("a_float", float(0.0123456789))
	print_asset_content(asset2)

	########################
	print '\ncreating asset 3'
	asset3 = oal.create_asset(os.path.join(os.getcwd(), "jahlogo.png"))
	print 'dir = %s' % os.path.join(os.getcwd(), "jahlogo.png")
	print asset3.get('location')
	#print asset3.get('filename')
	
	if asset3 is None:
		print '\tFailed'
	else:
		print '\tSucceeded'
		
	print_asset_content(asset3)
	print "\tadding extra metadata and modifiying guid..."
	#asset3.guid(oal.create_guid(str('{33333333-3333-3333-3333-333333333333}')))
	asset3.set("a_string", "Three")
	print_asset_content(asset3)

	########################
	print '\ncreating asset 4'
	asset4 = oal.create_asset()
	if asset4 is None:
		print '\tFailed'
	else:
		print '\tSucceeded'

	#asset4.guid(oal.create_guid(str('{44444444-4444-4444-4444-444444444444}')))
	asset4.set("a_string", "Four")
	print_asset_content(asset4)

	########################
	print '\ncreating asset 5'
	asset5 = oal.create_asset()
	if asset5 is None:
		print '\tFailed'
	else:
		print '\tSucceeded'
		
	#asset5.guid(oal.create_guid(str('{55555555-5555-5555-5555-555555555555}')))
	asset5.set("a_string", "Five")
	print_asset_content(asset5)

	########################
	print '\ncreating asset 6'
	asset6 = oal.create_asset()
	if asset6 is None:
		print '\tFailed'
	else:
		print '\tSucceeded'
		
	#asset6.guid(oal.create_guid(str('{66666666-6666-6666-6666-666666666666}')))
	asset6.set("a_string", "Six")
	print_asset_content(asset6)
	
	########################
	print '\nCreating some sets of assets...'
	print '\nCreating set1'
	set1 = oal.create_set(str("name for set1"))
	print '\tset name = %s' % set1.name()
	set1.name("set1's name")
	print '\tset name = %s' % set1.name()
	print 'Size of set1 = %d' % set1.size()
	if set1.empty() is True:
		print 'set1 is empty'
	else:
		print 'set1 is not empty'
		
	print 'pushing some assets onto back...'
	set1.push_back(asset1)
	set1.push_back(asset2)
	set1.push_back(asset3)
	set1.push_back(asset4)
	
	print 'Size of set1 = %d' % set1.size()
	if set1.empty() is True:
		print 'set1 is empty'
	else:
		print 'set1 is not empty'

	print 'List of assets:'	
	for a in set1:
		print "\t", a.guid()
		
	print "Asset at offset 0: ", set1.at(0).guid()
	print "Asset at offset 3: ", set1.at(3).guid()
	
	######################
	print '\ncreating set2 with asset3'
	set2 = oal.create_set(asset3, str("set2's name"))
	print '\tset name = %s' % set2.name()
	print 'Size of set2 = %d' % set2.size()
	if set2.empty() is True:
		print 'set2 is empty'
	else:
		print 'set2 is not empty'
		
	print 'pushing some assets onto back...'
	set2.push_back(asset4)
	set2.push_back(asset5)
	set2.push_back(asset6)

	print 'List of assets:'	
	for a in set2:
		print "\t", a.guid()
	
	######################
	print '\ncreating set3 with set1'
	set3 = oal.create_set(set1, str("set3's name"))
	print '\tset name = %s' % set3.name()
	print 'List of assets:'	
	for a in set3:
		print "\t", a.guid()
	print 'popping the last asset off the back...'
	set3.pop_back()
	print 'List of assets:'	
	for a in set3:
		print "\t", a.guid()
	print 'Inserting asset6 at offset 1'
	set3.insert(asset6, 1)
	print 'List of assets:'	
	for a in set3:
		print "\t", a.guid()
	print 'Inserting set1 at offset 3'
	set3.insert(set1, 3)
	print 'List of assets:'	
	for a in set3:
		print "\t", a.guid()
	print '\nRemoving asset6'
	set3.remove(asset6)
	print 'List of assets:'	
	for a in set3:
		print "\t", a.guid()
	
	######################
	print '\ncreating set4 with set1'
	set4 = oal.create_set(set1)
	print 'List of assets:'	
	for a in set4:
		print "\t", a.guid()
	print '\nClearing set'
	set4.clear()
	print 'List of assets:'	
	if set4.empty():
		print '\tEMPTY!'
	else:
		for a in set4:
			print "\t", a.guid()
	
	########################################################
	print "\nIntersection of set1 and set2:"
	intersection_set = oal.calculate_intersection(set1, set2)
	print_set_content(intersection_set)

	print "\nIntersection of set1 and set3:"
	intersection_set = oal.calculate_intersection(set1, set3)
	print_set_content(intersection_set)

	print "\nIntersection of set2 and set3:"
	intersection_set = oal.calculate_intersection(set2, set3)
	print_set_content(intersection_set)

	print "\nDifference between set1 and set2:"
	difference_set = oal.calculate_difference(set1, set2)
	print_set_content(difference_set)

	print "\nDifference between set1 and set3:"
	difference_set = oal.calculate_difference(set1, set3)
	print_set_content(difference_set)

	print "\nDifference between set2 and set3:"
	difference_set = oal.calculate_difference(set2, set3)
	print_set_content(difference_set)

	print "\nUnion of set1 and set2:"
	union_set = oal.calculate_union(set1, set2)
	print_set_content(union_set)

	print "\nUnion of set1 and set3:"
	union_set = oal.calculate_union(set1, set3)
	print_set_content(union_set)

	print "\nUnion of set2 and set3:"
	union_set = oal.calculate_union(set2, set3)
	print_set_content(union_set)
	
	###################################
	print "\nSearching set3 for a_string = Hello :-)"
	predicate = oal.key_value_regex_search_predicate("a_.*", "Hello :-\)")
	search_results_set = oal.search(set3, predicate)
	print_set_content(search_results_set)
	
	###################################
	print "\nSearching set3 for all png files"
	search_results_set = oal.search(set3, oal.location_filename_regex_predicate(".*", ".*.png"))
	print_set_content(search_results_set)
	
	###################################
	print_is_convertible(asset3)
	image = oal.convert_to_image(asset3)
	if image is None:
		print 'Failed to convert asset3 to image object'
	else:
		print 'Successfully converted asset3 to image object'
		print 'asset3 width = %s' % asset3.get("width")
		print 'asset3 height = %s' % asset3.get("height")
	
	###################################
	#asset4.set("location", "C:/Media/")
	#asset4.set("filename", "Donkey.mpeg")
	asset4.set("location", os.path.join(os.getcwd(), "mvi_2827.avi"))
	print_is_convertible(asset4)
	media = oal.convert_to_media(asset4) # Note: Cos oml is not exported as yet, there is convert_to_media in the bindings returns void!
	if media is None:
		print 'Failed to convert asset4 to media object'
	else:
		print 'Successfully converted asset4 to media object'
	print 'asset4 width = %s' % asset4.get("width")
	print 'asset4 height = %s' % asset4.get("height")
	print 'asset4 frames = %s' % asset4.get("frames")
	print 'asset4 video_streams = %s' % asset4.get("video_streams")
	print 'asset4 audio_streams = %s' % asset4.get("audio_streams")
	print 'asset4 fps = %s' % asset4.get("fps")
	print 'asset4 sar = %s' % asset4.get("sar")
	
	search_root_dir = oal.generate_guid()
	os.mkdir(search_root_dir)
	print search_root_dir
	
	full_search_root_dir = os.path.join(os.getcwd(), search_root_dir)
	print full_search_root_dir
	
	full_image_dir = os.path.join(full_search_root_dir, "image")
	os.mkdir(full_image_dir)
	print full_image_dir
	
	full_image2_dir = os.path.join(full_search_root_dir, "image2")
	os.mkdir(full_image2_dir)
	print full_image2_dir
	
	#copy jahlogo.png to newly created test folder
	shutil.copy("jahlogo.png", os.path.join(full_image_dir, "jahlogo.png"))
	shutil.copy("jahlogo.png", os.path.join(full_image2_dir, "jahlogo.png"))
	
	##############################################
	x = openpluginlib.discovery( openpluginlib.all_query_traits( "openassetlib", "", "filesystem", 0 ) )
	if x.size() == 0:
		print "No plugins discovered!"
	else:
		for y in x:
			print y.libname(), ':', y.name(), y.merit()
 			fs_plugin = y.create_plugin("")
 			#print fs_plugin
 			if fs_plugin is None:
 				print "Failed to create filesystem plugin"
 			else:
 				print "Successfully created filesystem plugin!  :-)"
 				break
 			
	print "Searching for .png files in root of test folders (non-recursive)"
	fs_search_set1 = oal.search(fs_plugin, ".*\.png", full_search_root_dir, False)
	#print fs_search_set1
	print_set_content(fs_search_set1)
	
	print "Searching for .png files in root of test folders (recursive)"
	fs_search_set2 = oal.search(fs_plugin, ".*\.png", full_search_root_dir, True)
	#print fs_search_set2
	print_set_content(fs_search_set2)
	
	try:
		for root, dirs, files in os.walk(search_root_dir, topdown=False):
			for name in files:
				os.remove(os.path.join(root, name))
			for name in dirs:
				os.rmdir(os.path.join(root, name))
		os.rmdir(search_root_dir) 
	except OSError:
		print 'OSError caught'
		pass

	
	##############################################
	x = openpluginlib.discovery( openpluginlib.all_query_traits( "openassetlib", "", "sqlite", 0 ) )
	if x.size() == 0:
		print "No plugins discovered!"
	else:
		for y in x:
			print y.libname(), ':', y.name(), y.merit()
 			db_plugin = y.create_plugin("")
 			print db_plugin
 			if db_plugin is None:
 				print "Failed to create sqlite database plugin"
 			else:
 				print "Successfully created sqlite database plugin!  :-)"
 				break

	store_set = oal.create_set()
	store_set.push_back(asset3)
	store_set.push_back(asset4)
	
	oal.store_image(asset4, image, "jahlogo.png")
	
	failed_to_store_set = oal.store(db_plugin, store_set)
	if failed_to_store_set is None:
		print '\nSet successfully stored'
	else:
		print 'The following assets failed to get stored in the db..'
		for failed_asset in failed_to_store_set:
			print '\t%s' % failed_asset.guid()
		print '\n'
		
	restore_set = oal.create_set()
	
	asset_to_restore1 = oal.create_asset(asset3.guid())
	#asset_to_restore1.guid(oal.create_guid("{33333333-3333-3333-3333-333333333333}"))
	restore_set.push_back(asset_to_restore1)
	
	asset_to_restore2 = oal.create_asset(asset4.guid())
	#asset_to_restore2.guid(oal.create_guid("{44444444-4444-4444-4444-444444444444}"))
	restore_set.push_back(asset_to_restore2)
	
	restored_set = oal.restore(db_plugin, restore_set)
	if restored_set is None:
		print '\nSet failed to restored'
	else:
		print 'Successfully restored assets...'
		print_set_content(restored_set)
		if restored_set.at(0).guid() == asset_to_restore1.guid():
			print 'restored asset at set offset 0 was %s' % asset_to_restore1.guid()
		if restored_set.at(1).guid() == asset_to_restore1.guid():
			print 'restored asset at set offset 1 wasnt %s' % asset_to_restore1.guid()
			print 'it was %s' % restored_set.at(1).guid()
			
		
	image2 = oal.restore_image(restored_set.at(1), "jahlogo.png")
	if image2 is None:
		print 'Failed to restore image'
	else:
		print 'Successfully restored image'
	
	##############################################
	set_to_save = oal.create_set(str("abc123xyz"))
	set_to_save.push_back(asset1)
	set_to_save.push_back(asset2)
	print '\nSaving following set...'
	print_set_content(set_to_save)
	xmlfilename = "test_set.xml"
	if oal.save_set(db_plugin, xmlfilename, set_to_save) is False:
		print 'Failed to save set'
	else:
		print 'Set saved'
	
	print '\nLoading set from %s...' % xmlfilename
	loaded_set = oal.load_set(db_plugin, xmlfilename)
	if loaded_set is None:
		print 'Failed to load set'
	else:
		print 'Loaded set...'
		print_set_content(loaded_set)

	oal.uninit()
	print '\nExercises complete - please check results for anomalies!'
	

#
# Run the main method if required
#

if __name__ == "__main__":
	main( )
	
