#!/usr/bin/env python

import sys
import os
import time
import argparse

class Language:
	def __init__(self, code, description):
		self.code = code
		self.description = description

class Localizer:

	def __init__(self, base_dir, filename):
		self.base_dir = base_dir
		self.remaster_dir = os.path.join(self.base_dir, "remaster")
		self.root_dir = os.path.join(self.base_dir, "root")
		self.initrd_dir = os.path.join(self.base_dir, "initrd")        
		self.mount_dir = "/tmp/iso-localize-cdrom"
		self.squash_mount_dir = "/tmp/iso-localize-squash"

		self.languages = []
		self.language_codes = []
		file = open("/usr/lib/linuxmint/iso-localize/languages.list", "r")
		for line in file:
			elements = line.strip().split("=")			
			if len(elements) == 2: 
				language = Language(elements[0], elements[1])
				self.languages.append(language)
				self.language_codes.append(language.code)
		file.close()

		print "Available languages: "
		for language in self.languages:
			print "    - %s (%s)" % (language.code, language.description)
		
		self.language = raw_input("Please select a language: ").strip()
		self.isolinux_language = self.language
		
		if not self.language in self.language_codes:
			print "Unkown language code: " + self.language
			sys.exit(1)		
		
		if self.language == "pt":
			print "Available variants: "
			print "    - pt_PT (Portugal)"
			print "    - pt_BR (Brazil)"
			self.isolinux_language = raw_input("Please select a variant: ").strip()
			if not self.isolinux_language in ["pt_PT", "pt_BR"]:
				print "Unkown variant code: " + self.isolinux_language
				sys.exit(1)
		if self.language == 'de':
			print 'Aviable variants: '
			print '		de_AT (Austria)'
			print '		de_CH (Switzerland)'
			print '		de_DE (Germany)'
			self.isolinux_language = raw_input('Please select a variant: ').strip()
			if not self.isolinux_language in ['de_AT', 'de_CH', 'de_DE']:
				print 'Unknown variant code: {0}'.format(self.isolinux_language)
				sys.exit(1)
			self.isolinux_language = '{0}.UTF-8'.format(self.isolinux_language)
		
		self.source_live_cd_filename = filename
		self.build_live_cd_filename = self.source_live_cd_filename.replace(".iso", "-" + self.language + ".iso")
		
		self.clean_up()

		os.system("mkdir -p " + self.remaster_dir)
		os.system("mkdir -p " + self.root_dir)
		os.system("mkdir -p " + self.initrd_dir)
		os.system("mkdir -p " + self.mount_dir) 
		os.system("mkdir -p " + self.squash_mount_dir) 

		self.extract()
		self.chroot_operations()
		self.build()
		self.clean_up()
               
	def chroot_operations(self):
		print "***** Localizing system"
		os.system('cp -f /etc/resolv.conf ' + os.path.join(self.base_dir, "root/etc/resolv.conf"))		     
		os.system('mount --bind /proc \"' + os.path.join(self.base_dir, "root/proc") + '\"')
		os.system('mv -f \"' + os.path.join(self.base_dir, "root/etc/wgetrc") + '\" \"' + os.path.join(self.base_dir, "root/etc/wgetrc.orig") + '\"')
		os.system('cp -f /etc/wgetrc ' + os.path.join(self.base_dir, "root/etc/wgetrc"))	
		
		print "------- Modifying liveCD menu"		
		isolinux = []
		file = open(os.path.join(self.base_dir, "remaster/isolinux/isolinux.cfg"), "r")
		for line in file:
			if "menu title" in line:
				title = line.replace("menu title", "").strip()
				print "--- Current title: " + title
				new_title = raw_input("New title: ")
				new_line = line.replace(title, new_title)
			elif "menu label" in line:
				label = line.replace("menu label", "").strip()
				print "--- Current label: " + label
				new_label = raw_input("New label: ")
				new_line = line.replace(label, new_label)
			else:
				new_line = line.replace('initrd=/casper/initrd.gz', 'initrd=/casper/initrd.gz locale={0} console-setup/layoutcode={1}'.format(self.isolinux_language, self.language))
				new_line = new_line.replace('initrd=/casper/initrd.lz', 'initrd=/casper/initrd.lz locale={0} console-setup/layoutcode={1}'.format(self.isolinux_language, self.language))
			isolinux.append(new_line)
		file.close()
		file = open(os.path.join(self.base_dir, "remaster/isolinux/isolinux.cfg"), "w")
		file.writelines(isolinux)
		file.close()		
					
		print "------- Installing Language packs"
		command = 'apt-get install --force-yes -y \
				language-pack-xx \
				language-pack-gnome-xx-base \
				language-pack-gnome-xx \
				thunderbird-locale-xx \
				libreoffice-help-xx	\
				libreoffice-l10n-xx'.replace('xx', self.language)
		os.system('chroot {0} /bin/sh -c \"{1}\"'.format(self.root_dir, command))
		command = "apt-get install --force-yes -y language-pack-kde-xx-base language-pack-kde-xx".replace("xx", self.language)
		os.system("chroot " + self.root_dir + " /bin/sh -c \""+ command +"\"")
		
		command = 'dpkg-reconfigure --frontend=readline tzdata'
		os.system('chroot {0} /bin/sh -c \"{1}\"'.format(self.root_dir, command))
		
		os.system('mv -f \"' + os.path.join(self.base_dir, "root/etc/wgetrc.orig") + '\" \"' + os.path.join(self.base_dir, "root/etc/wgetrc") + '\"')
		os.system('rm -rf \"' + os.path.join(self.base_dir, "root/etc/resolv.conf") + '\"')		
		os.system('umount --force \"' + os.path.join(self.base_dir, "root/proc/") + '\"')

	def extract(self):
		print "***** Extracting ISO file"
		os.system('mount -o loop \"' + self.source_live_cd_filename + '\" ' + self.mount_dir)  
		print "------- Copying files"
		os.system('rsync -at --del ' + self.mount_dir + '/ \"' + self.remaster_dir + '\"')

		filename = os.path.join(self.mount_dir, 'isolinux/isolinux.cfg')
		with open(filename) as f:
			for line in f:
				if 'menu title' in line:
					old_description = line.replace("menu title Welcome to", "").strip()
					self.build_live_cd_description = '{0} {1}'.format(old_description, self.language.upper())

		print "------- Decompressing filesystem"
		os.system('mount -t squashfs -o loop ' + self.mount_dir + '/casper/filesystem.squashfs \"' + self.squash_mount_dir + '\"')						
		os.system('rsync -at --del \"' + self.squash_mount_dir + '\"/ \"' + self.root_dir + '\"')
		os.system('umount --force \"' + self.squash_mount_dir + '\"')
				
		os.system('chmod 6755 \"' + os.path.join(self.base_dir, "root/usr/bin/sudo") + '\"')
		os.system('chmod 0440 \"' + os.path.join(self.base_dir, "root/etc/sudoers") + '\"')
				
		#print "-------- Extracting Initial Ram disk"
		#if os.path.exists(self.mount_dir + '/casper/initrd.lz'):
		#	os.system('cd \"' + os.path.join(self.base_dir, "initrd/") + '\"; lzma -dc -S .lz ' + self.mount_dir + '/casper/initrd.lz | cpio -id')
		#elif os.path.exists(self.mount_dir + '/casper/initrd.gz'):
		#	os.system('cd \"' + os.path.join(self.base_dir, "initrd/") + '\"; cat ' + self.mount_dir + '/casper/initrd.gz | gzip -d | cpio -i')                   
			
		os.system("umount --force " + self.mount_dir)
		

	def build(self):              
		print "***** Assembling new ISO"
		#os.system('cd \"' + os.path.join(self.base_dir, "initrd/") + '\"; find | cpio -H newc -o | lzma -7 > ../initrd.lz' + '; mv -f ../initrd.lz \"' + os.path.join(self.base_dir, "remaster/casper/initrd.lz") + '\"')

		print "------- Compressing filesystem"
		q = ' dpkg-query -W --showformat=\'${Package} ${Version}\n\' '
		os.system('chroot \"' + os.path.join(self.base_dir, "root/") + '\"' + q + ' > \"' + os.path.join(self.base_dir, "remaster/casper/filesystem.manifest") + '\"' )
		os.system('cp -f \"' + os.path.join(self.base_dir, "remaster/casper/filesystem.manifest") + '\" \"' + os.path.join(self.base_dir, "remaster/casper/filesystem.manifest-desktop") + '\"')
		if os.path.exists(os.path.join(self.base_dir, "remaster/casper/filesystem.squashfs")):                    
			os.system('rm -Rf \"' + os.path.join(self.base_dir, "remaster/casper/filesystem.squashfs") + '\"')
		os.system(' mksquashfs \"' + os.path.join(self.base_dir, "root/") + '\"' + ' \"' + os.path.join(self.base_dir, "remaster/casper/filesystem.squashfs") + '\"')

		print "------- Updating manifests"         
		os.system("/usr/lib/linuxmint/iso-localize/updateManifest.sh " + self.base_dir)
		print "------- Updating md5 sums"
		os.system('rm ' + os.path.join(self.base_dir, "remaster/") + ' md5sum.txt')
		os.system('cd \"' + os.path.join(self.base_dir, "remaster/") + '\"; ' + 'find . -type f -print0 | xargs -0 md5sum > md5sum.txt')
		#Remove md5sum.txt from md5sum.txt
		os.system("sed -e '/md5sum.txt/d' " + os.path.join(self.base_dir, "remaster/") + "md5sum.txt > " + os.path.join(self.base_dir, "remaster/") + "md5sum.new")
		os.system("mv " + os.path.join(self.base_dir, "remaster/") + "md5sum.new " + os.path.join(self.base_dir, "remaster/") + "md5sum.txt")
		#Remove boot.cat from md5sum.txt
		os.system("sed -e '/boot.cat/d' " + os.path.join(self.base_dir, "remaster/") + "md5sum.txt > " + os.path.join(self.base_dir, "remaster/") + "md5sum.new")
		os.system("mv " + os.path.join(self.base_dir, "remaster/") + "md5sum.new " + os.path.join(self.base_dir, "remaster/") + "md5sum.txt")
		#Remove isolinux.bin from md5sum.txt
		os.system("sed -e '/isolinux.bin/d' " + os.path.join(self.base_dir, "remaster/") + "md5sum.txt > " + os.path.join(self.base_dir, "remaster/") + "md5sum.new")
		os.system("mv " + os.path.join(self.base_dir, "remaster/") + "md5sum.new " + os.path.join(self.base_dir, "remaster/") + "md5sum.txt")

		# remove existing iso
		if os.path.exists(self.build_live_cd_filename):			
			os.system('rm -rf \"' + self.build_live_cd_filename + '\"')                
		print "------- Building new ISO file"
		if os.path.isfile('/usr/bin/genisoimage'):
			os.system('genisoimage -o \"{0}\" \
						-b \"isolinux/isolinux.bin\" \
						-c \"isolinux/boot.cat\" \
						-no-emul-boot \
						-boot-load-size 4 \
						-boot-info-table -V \"{1}\" \
						-cache-inodes -r -J -l \"{2}\"'.format(
						self.build_live_cd_filename,
						self.build_live_cd_description,
						self.remaster_dir))
		if os.path.isfile('/usr/bin/mkisofs'):
			os.system('mkisofs -o \"{0}\" \
						-b \"isolinux/isolinux.bin\" \
						-c \"isolinux/boot.cat\" \
						-no-emul-boot \
						-boot-load-size 4 \
						-boot-info-table -V \"{1}\" \
						-cache-inodes -r -J -l \"{2}\"'.format(
						self.build_live_cd_filename,
						self.build_live_cd_description,
						self.remaster_dir))
		        
		print "***** Finished!"
		print "------- ISO Located: " + self.build_live_cd_filename  
		if os.path.exists("/usr/bin/aplay"):
			os.system("/usr/bin/aplay /usr/lib/linuxmint/iso-localize/done.wav")

	def clean_up(self):
		print '------- Cleaning up'
		if os.path.ismount(self.mount_dir):
			self.unmount_iso_file()
		os.system('rm -rf {0}'.format(self.mount_dir))
		
		if os.path.ismount(self.squash_mount_dir):
			self.unmount_squashfs()
		os.system('rm -rf {0}'.format(self.squash_mount_dir))
		
		if os.path.isdir(self.base_dir):
			os.system('rm -rf {0}'.format(self.base_dir))


if __name__ == "__main__":  
    if os.getuid() != 0 :
        print "You must run with root privileges"
        sys.exit(1)        
    else :
		parser = argparse.ArgumentParser()
		parser.add_argument('FILENAME', help='name of the iso file')
		parser.add_argument('-b', '--builddirectory',
							default='/tmp/iso-localize',
							help='path to store temporary files created during runtime')
		args = parser.parse_args()
		rec = Localizer(args.builddirectory, args.FILENAME)
