#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
   = = = = = = = = = = = = = = = = = = = = = =
   =                patcha                   =
   = = = = = = = = = = = = = = = = = = = = = =
   
   This script is part of the desktop management solution opsi
   (open pc server integration) http://www.opsi.org
   
   Copyright (C) 2008 uib GmbH
   
   http://www.uib.de/
   
   All rights reserved.
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 as
   published by the Free Software Foundation.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   
   @copyright:	uib GmbH <info@uib.de>
   @author: Jan Schneider <j.schneider@uib.de>
   @license: GNU General Public License version 2
"""

__version__ = '0.2.4'

# Imports
import os, sys, re, getopt, codecs

# OPSI imports
from OPSI.Logger import *
from OPSI.System import *

# Get Logger instance
logger = Logger()
logger.setConsoleLevel(LOG_ERROR)

# Globals
placeholderRegex = re.compile('^(.*)#\@(\w+)\**#+(.*)$')
placeholderRegexNew = re.compile('^(.*)%([\w\-]+)%(.*)$')

def usage():
	print u"Usage: %s "
	print u"   Options:"

def usage():
	print u"\nUsage: %s [-h|-v] [-f <params file>] <patch file>" % os.path.basename(sys.argv[0])
	print u"  Fill placeholders in file <patch file>"
	print u"Options:"
	print u"  -v                Show version information and exit"
	print u"  -h                Show this help"
	print u"  -f <params file>  File containig key value pairs"
	print u"                    If option not given key value pairs from kernel cmdline are used"
	print u""

def main(argv):
	paramsFile = u''
	patchFile = u''
	params = {}
	
	try:
		(opts, args) = getopt.getopt(argv, "hvf:")
		for (opt, arg) in opts:
			if (opt == "-f"):
				paramsFile = arg
			elif (opt == "-h"):
				usage()
				sys.exit(0)
			elif (opt == "-v"):
				print __version__
				sys.exit(0)
		
		if (len(args) < 1):
			usage()
			sys.exit(1)
		
		patchFile = args[0]
	except getopt.GetoptError:
		usage()
		sys.exit(1)
	
	if paramsFile:
		logger.notice(u"Reading params from file '%s'" % paramsFile)
		params = getParamsFromFile(paramsFile)
	else:
		logger.notice(u"Getting params from kernel commandline")
		params = getKernelParams()
	
	logger.debug(u"Params:")
	for (key, value) in params.items():
		logger.debug(u"   %s = %s" % (key, value))
	
	patchPatchFile(patchFile, params)
	
	
def patchPatchFile(patchFile, params):
	f = None
	encodings = ('cp1250', 'utf-8', 'utf-16', 'replace')
	if patchFile.lower().endswith('.xml'):
		encodings = ('utf-8', 'utf-16', 'cp1250', 'replace')
	encoding = None
	for encoding in encodings:
		if (encoding == 'replace'):
			encoding = 'utf-8'
			f = codecs.open(patchFile, 'r', encoding, 'replace')
		else:
			try:
				f = codecs.open(patchFile, 'r', encoding)
			except UnicodeEncodeError:
				continue
		break
	lines = f.readlines()
	f.close()
	
	f = codecs.open(patchFile, 'w', encoding)
	for line in lines:
		lb = u'\n'
		if line.endswith(u'\r\n'):
			lb = u'\r\n'
		line = line.rstrip()
		match = re.search(placeholderRegexNew, line)
		while match:
			key = match.group(2)
			if not key in params.keys():
				logger.warning(u"Cannot patch placeholder '%s' in file '%s': param not defined" \
							% (key, patchFile))
				break
			else:
				logger.notice(u"Patching placeholder '%s' in file '%s'" % (key, patchFile))
				line = unicode(match.group(1) + params[key] + match.group(3))
			match = re.search(placeholderRegexNew, line)
		match = re.search(placeholderRegex, line)
		while match:
			key = match.group(2)
			if not key in params.keys():
				logger.warning(u"Cannot patch placeholder '%s' in file '%s': param not defined" \
							% (key, patchFile))
				break
			else:
				logger.notice(u"Patching placeholder '%s' in file '%s'" % (key, patchFile))
				line = unicode(match.group(1) + params[key] + match.group(3))
			match = re.search(placeholderRegex, line)
		f.write(line + lb)
	f.close()
	
def getParamsFromFile(paramsFile):
	result = {}
	f = codecs.open(paramsFile, 'r', 'utf-8', 'replace')
	for line in f.readlines():
		line = line.strip()
		if not line or line.startswith('#') or line.startswith(';'):
			continue
		(key, value) = (line, u'')
		if (line.find(u'=') != -1):
			(key, value) = line.split(u'=', 1)
		result[key.strip()] = value.strip()
	f.close()
	return result

if (__name__ == "__main__"):
	exception = None
	
	try:
		main(sys.argv[1:])
	
	except SystemExit, e:
		pass
		
	except Exception, e:
		exception = e
	
	if exception:
		logger.logException(exception)
		print >> sys.stderr, u"ERROR: %s" % exception
		sys.exit(1)
	
	sys.exit(0)

