#!/usr/bin/python
# vim:fileencoding=iso-8859-2

from time import strftime
from optparse import OptionParser
from os import path, popen, rename
import locale, os, sre, sys

__version__ = '0.1'

loc = locale.getpreferredencoding()
if loc != 'ISO-8859-2':
    def N_(message):
	'''Aha! We're gonna convert messages too.'''
	return message.decode('iso-8859-2').encode(loc)
else:
    def N_(message):
	'''Nope, we're on Bart's box probably ;]'''
	return message


def warn(message):
    '''Speeks to stderr.'''
    sys.stderr.write('%s\n' % message)


class RecodeSpec:
    '''Handles various operations performed on files and data.'''

    def __init__(self, filename):
	'''Aaaa, init ;]'''
	self.spec = filename
	self.regexp = sre.compile('%changelog.*\n', sre.I)
	self.Date = strftime('%a %b %d %Y')


    def read_spec(self):
	'''This one reads spec (or not).'''
	try:
	    fh = open(self.spec, 'r')
	    try:
		data = fh.read()
		return data
	    finally:
		fh.close()
	except IOError, error:
	    warn('%s: %s' % (self.spec, error[1]))
	    return False


    def write_old_spec(self, data, from_what):
	'''Writes original spec using filename "spec.encoding.index"'''
	if from_what == 'from_utf':
	    encoding = 'UTF-8'
	if from_what == 'from_iso':
	    encoding = 'ISO-8859-2'
	i = 9
	fileout = ('%s.%s' % (self.spec, encoding))
	while i > 0:
	    if path.exists('%s.%d' % (fileout, i)):
		try:
		    rename('%s.%d' % (fileout, i), '%s.%d' % (fileout, i+1))
		except OSError or IOError, error:
		    warn('%s: %s' % (self.spec, error[1]))
		    pass
	    i -= 1
	try:
	    fh = open('%s.1' % fileout, 'w')
	    fh.truncate()
	    try:
		fh.write(data)
		return True
	    finally:
		fh.close()
	except OSError or IOError, error:
	    warn('%s: %s' % (self.spec, error[1]))
	    return False


    def write_new_spec(self, newdata):
	'''New file is comming!'''
	try:
	    fh = open(self.spec, 'w')
	    fh.truncate()
	    try:
		fh.write(newdata)
		return True
	    finally:
		fh.close()
	except IOError, error:
	    warn('%s: %s' % (self.spec, error[1]))
	    return False


    def update_changelog(self, data, to_what):
	'''This one is pretty usefull (or not). Adds to %changelog current date,
	packager's name and e-mail and message "Converted to $encoding.'''
	try:
	    packager = popen('rpm -E %packager').read()
	except:
	    pass

	if packager.find('%packager') != -1:
	    warn(N_('Warnung: Brak pola %packager w ~/.rpmmacros'))
	    packager = '\n'
	if to_what == 'to_utf':
	    encoding = 'UTF-8'
	if to_what == 'to_iso':
	    encoding = 'ISO-8859-2'
	string = ('%s %s- Spec converted to %s' % (self.Date, packager, encoding))
	match = sre.search(self.regexp, data, 1)
	if match != None:
	    newdata = sre.sub(self.regexp, ('%%changelog\n* %s\n\n' % string), data, 1)
	    return (None, newdata)
	else:
	    return (None, False)


    def to_utf(self, data):
	'''Converts from ISO to UTF.'''
	try:
	    newdata = data.decode('iso-8859-2').encode('utf8')
	    return (True, newdata)
	except UnicodeError, error:
	    return (False, error[2], data[error[3]])


    def to_iso(self, data):
	'''Converts from UTF to ISO.'''
	try:
	    newdata = data.decode('utf8').encode('iso-8859-2')
	    return (True, newdata)
	except UnicodeError, error:
	    return (False, error[2], data[error[2]])


def main():
    '''Main proc, main code is at the bottom. Nothing interesting but don't remove it.'''
    usage = (N_('sconv [-chisuv|--usage] spec [spec] ...'))
    version = (N_('sconv, wersja %s  Copyright (C) 2005 Bart Kreska\n') % __version__)
    description = (N_('sconv - konwerter speców UTF-8 <==> ISO-8859-2'))

    parser = OptionParser(usage=usage, version=False, add_help_option=False,
	description=description)

    parser.add_option('-c', '--changelog', help=N_('Aktualizuje sekcję %changelog'),
	action='store_true', default=False)
    parser.add_option('-h', '--help', help=N_('Wyświetla tę pomoc i kończy'),
	action='store_true', default=False)
    parser.add_option('-i', '--to-iso', help=N_('Konwertuje plik UTF-8 na ISO-8859-2'),
	action='store_true', default=False)
    parser.add_option('-s', '--stdout', help=N_('Nie zapisuje plików, drukuje na STDOUT'),
	action='store_true', default=False)
    parser.add_option('-u', '--to-utf', '--to-utf8', help=N_('Konwertuje plik ISO-8859-2 na UTF-8'),
	action='store_true', default=False)
    parser.add_option('-v', '--version', help=N_('Wyświetla wersję programu i kończy'),
	action='store_true', default=False)
    parser.add_option('--usage', help=N_('Wyświetla skróconą pomoc i kończy'),
	action='store_true', default=False)

    (options, args) = parser.parse_args()

    if not sys.argv[1:]:
	parser.print_usage()
	sys.exit(2)
    if options.version:
	print version
	sys.exit(0)
    if options.help:
	parser.print_help()
	sys.exit(0)
    if options.usage:
	parser.print_usage()
	sys.exit(0)
    if options.to_iso and options.to_utf:
	warn(N_('Prrrr, albo -i albo -u'))
	sys.exit(2)
    if options.to_iso and not args or options.to_utf and not args:
	warn(N_('Ej no mistrzu, podaj jakiś plik może, hę?'))
	sys.exit(2)
    if not options.to_iso and not options.to_utf:
	parser.print_usage()
	sys.exit(2)

    for arg in args:
	spec = RecodeSpec(arg)
	data = spec.read_spec()
	if data and options.to_utf:
	    recoded = spec.to_utf(data)
	    if recoded[0] == False:
		warn(N_('Error: ISO ==> UTF: Niedozwolony znak na pozycji %s: %s') \
		    % (recoded[1], recoded[2]))
	    else:
		if options.changelog:
		    recoded = spec.update_changelog(recoded[1], 'to_utf')
		if options.stdout:
		    sys.stdout.write(recoded[1])
		else:
		    if spec.write_old_spec(data, 'from_iso'):
			spec.write_new_spec(recoded[1])

	if data and options.to_iso:
	    recoded = spec.to_iso(data)
	    if recoded[0] == False:
		warn(N_('Error: UTF ==> ISO: Niedozwolony znak na pozycji %s: %s') \
		    % (recoded[1], recoded[2]))
	    else:
		if options.changelog:
		    recoded = spec.update_changelog(recoded[1], 'to_iso')
		if options.stdout:
		    sys.stdout.write(recoded[1])
		else:
		    if spec.write_old_spec(data, 'from_utf'):
			spec.write_new_spec(recoded[1])


if __name__ == '__main__':
    main()

# highlight 2.4.1, theme: acid