from SCons.Script.SConscript import SConsEnvironment
import SCons.Defaults
import SCons
from SCons.Script import *
import os
import glob
import shutil
import subprocess

def InstallLib(env, files):
	installfiles = []
	if env['PLATFORM'] == 'win32' or env['PLATFORM'] == 'cygwin':
		installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'lib'), files))
		for f in files:
			if env['PLATFORM'] == 'win32':
				env.AddPostAction(f, 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2')
			if isinstance(f, SCons.Node.Node):
				f = f.rstr()	
			installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'bin'), f[0:-4] + env['SHLIBSUFFIX']))
	else:
		installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'lib'), files))		
	return installfiles

def InstallPlugin(env, files):
	installfiles = []
	if env['PLATFORM'] == 'win32' or env['PLATFORM'] == 'cygwin':
		installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'lib', 'vos', 'plugins'), files))
		for f in files:
			if env['PLATFORM'] == 'win32':
				env.AddPostAction(f, 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2')
			if isinstance(f, SCons.Node.Node):
				f = f.rstr()	
			installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'bin'), f[0:-4] + env['SHLIBSUFFIX']))
	else:
		installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'lib', 'vos', 'plugins'), files))
	return installfiles

def createPkgInfo(target, source, env):
	pi = file(target[0].rstr(), 'w')
	pi.write('APPL????')
	pi.close()

def writePlistEntry(pi, k, v):
	pi.write('       <key>')
	pi.write(k)
	pi.write('</key>\n')
	pi.write('       <string>')
	pi.write(v)
	pi.write('</string>\n')

def createInfoplist(target, source, env, extraEntries, icns):
	pi = file(target[0].rstr(), 'w')
	pi.write("""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
""")
	writePlistEntry(pi, 'CFBundleDevelopmentRegion', 'English')
	writePlistEntry(pi, 'CFBundleExecutable', os.path.basename(source[0].rstr()))
	writePlistEntry(pi, 'CFBundleName', os.path.basename(source[0].rstr()))
	writePlistEntry(pi, 'CFBundlePackageType', 'APPL')
	writePlistEntry(pi, 'CFBundleVersion', '1.0')
	if icns != None:
		writePlistEntry(pi, 'CFBundleIconFile', icns)
	if extraEntries != None:
		pi.write(extraEntries)
	pi.write("""</dict>
</plist>
""")
	pi.close()

def SetupDylibBundle(target, source, env):
	for s in source:
		shutil.copy(s.rstr(), os.path.dirname(target[0].rstr()))
	if env['BUILDCFG'] == 'release':
		for t in target:
			subprocess.call(['strip', '-S', t.rstr()])
	for t in target:
		proc = os.popen('otool -DX '+t.rstr(), 'r')
		id = proc.readline()[0:-1]   # chomp the newline
		proc.close()
		subprocess.call(['install_name_tool', '-id', '@executable_path/'+os.path.basename(t.rstr()), t.rstr()])
		for t2 in target:
			if not os.path.islink(t2.rstr()):
				subprocess.call(['install_name_tool', '-change', id, '@executable_path/'+os.path.basename(t.rstr()), t2.rstr()])

def InstallConsoleProgram(env, files):
	installfiles = []
	if env['PLATFORM'] == 'win32':
		for f in files:
			env.AddPostAction(f, 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1')
			fname = os.path.basename(f.rstr())
			installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'bin'), fname))
	else:
		installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'bin'), files))
	return installfiles

def InstallGUIProgram(env, files, osxIcon=None, extraInfoPlist=None, resources=[]):
	installfiles = []
	if env['PLATFORM'] == 'darwin':
		for f in files:
			fname = os.path.basename(f.rstr())
			src = [f]
			dst = [os.path.join(env['DESTDIR'], 'bin', fname+'.app', 'Contents', 'MacOS', fname)]
			for a in glob.glob(os.path.join(env['THIRDPARTY_STAGEDIR'], 'lib', '*.dylib')):
				if not os.path.islink(a):
					src.append(a)
					dst.append(os.path.join(env['DESTDIR'], 'bin', fname+'.app', 'Contents', 'MacOS', os.path.basename(a)))
			
			installfiles.extend(env.Command(dst, src, SetupDylibBundle))
			installfiles.extend(env.Command(os.path.join(env['DESTDIR'], 'bin', 
						 fname+'.app', 'Contents', 'PkgInfo'),
				    f,
				    createPkgInfo))

			def CreateInfoplist(target, source, env):
				createInfoplist(target, source, env, extraInfoPlist, osxIcon)

			installfiles.extend(env.Command(os.path.join(env['DESTDIR'], 'bin', 
							     fname+'.app', 'Contents', 'Info.plist'),
						f,
						CreateInfoplist))
			if osxIcon != None:
				installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'bin', fname+'.app', 'Contents', 'Resources'),
							osxIcon))
			for r in resources:
				installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'bin', fname+'.app', 'Contents', 'Resources'),
							r))
		return installfiles
	else:
		return InstallConsoleProgram(env, files)

def InstallInclude(env, files, subdir=''):
	installfiles = []
	installfiles.extend(env.Install(os.path.join(env['DESTDIR'], 'include', subdir), files))
	return installfiles

def CreateOSXDiskImage(env, volumename, size, files):
	def CreateDMG(target, source, env):
		dmgfile = target[0].rstr()[0:-4] + '.tmp.dmg'
		if os.path.exists(target[0].rstr()):
			os.unlink(target[0].rstr())
		if os.path.exists(dmgfile):
			os.unlink(dmgfile)
		subprocess.call(['hdiutil', 'create', 
				 '-megabytes', str(size), 
				 dmgfile, 
				 '-fs', 'HFS+', 
				 '-volname', os.path.basename(volumename),
				 '-layout', 'NONE'])
		subprocess.call(['hdid', dmgfile])
		for a in source:
			fname = os.path.realpath(a.rstr())
			print fname
			if fname.startswith(env['STAGEDIR']+'/bin'):
				fname = fname[len(env['STAGEDIR']+'/bin')+1:]
			if fname.startswith(env['STAGEDIR']):
				fname = fname[len(env['STAGEDIR'])+1:]
			print fname
			targetdir = os.path.join('/Volumes', os.path.basename(volumename), os.path.dirname(fname))
			print targetdir
			if not os.path.exists(targetdir):
				os.makedirs(targetdir)
			shutil.copy(a.rstr(), targetdir)
		subprocess.call(['hdiutil', 'eject', os.path.join('/Volumes', os.path.basename(volumename))])
		subprocess.call(['hdiutil', 'convert', dmgfile, '-format', 'UDBZ', '-o', target[0].rstr()])
		os.unlink(dmgfile)

	return env.Command(volumename+'.dmg', files, CreateDMG)

SConsEnvironment.InstallLib = InstallLib
SConsEnvironment.InstallPlugin = InstallPlugin
SConsEnvironment.InstallGUIProgram = InstallGUIProgram
SConsEnvironment.InstallConsoleProgram = InstallConsoleProgram
SConsEnvironment.InstallInclude = InstallInclude
SConsEnvironment.CreateOSXDiskImage = CreateOSXDiskImage

def setupUninstall(env):
	uninst = []
	e = env.Dir(os.path.join(env['DESTDIR'], 'bin'))
	for a in e.children():
		uninst.append(SCons.Defaults.Delete(a.rstr()))
	e = env.Dir(os.path.join(env['DESTDIR'], 'lib'))
	for a in e.children():
		uninst.append(SCons.Defaults.Delete(a.rstr()))
	e = env.Dir(os.path.join(env['DESTDIR'], 'include'))
	for a in e.children():
		uninst.append(SCons.Defaults.Delete(a.rstr()))
	env.Command('uninstall', None, uninst)

def initInstall(env):
	env.Append(CPPPATH = [os.path.realpath(os.path.join(env['DESTDIR'], 'include'))])
	env.Append(LIBPATH = [os.path.realpath(os.path.join(env['DESTDIR'], 'lib'))])

	if env['PLATFORM'] != 'win32':
		env.Default(env.Install(os.path.join(env['STAGEDIR'], 'bin'),
					os.path.join('scripts', 'run.sh')))

def copyDLLs(env):
	if env['PLATFORM'] == 'win32':
		for g in glob.glob(os.path.join(env['THIRDPARTY_STAGEDIR'], 'bin', '*.dll')):
			env.Default(env.Install(os.path.join(env['STAGEDIR'], 'bin'), g))

import scripts
scripts.AddInitializer(initInstall)
scripts.AddFinalizer(setupUninstall)
scripts.AddFinalizer(copyDLLs)
