#!/usr/bin/python3

# This isn't a completely working script yet, the framework is there
# This script interactively renames gaim logs based on a regex in the first line
# It is useful if you have a bunch of gaim logs not in their regular dirs
# for eg: if you accidentally deleted them and used an undelete program
# It will need customisation for your needs

import os
import re
import sys

# Requires urwid: http://urwid.org/
import urwid
import urwid.curses_display

class GaimLogRenamer:
	text_regex = re.compile(r'^Conversation with ([^ /]*)[^ ]* at ([^-]*)-([^-]*)-([^ ]*) ([^:]*):([^:]*):([^ ]*) on ([^ /]*)[^ ]* \(([^)]*)\).*$')
	html_regex = re.compile(r'^.*<title>Conversation with ([^ /]*)[^ ]* at ([^-]*)-([^-]*)-([^ ]*) ([^:]*):([^:]*):([^ ]*) on ([^ /]*)[^ ]* \(([^)]*)\)</title>.*')
	root = '/home/pabs/chat/im-recovery/logs'
	compare = '/usr/bin/meld'
	interactive = 0
	skip_broken = 0
	
	def __init__(self):
		if sys.stdout.isatty():
			self.interactive = 1
		if self.interactive:
			self.banner = urwid.Text( ('banner', "pabs' mass gaim chat file renamer"), align="center")
			self.stats_text = urwid.Text( ('stats', 'STATS GO HERE'), align="center" )
			self.stats = urwid.AttrWrap( self.stats_text, 'stats' )
			self.keys_text = urwid.Text( ('keys', 'q = quit n = next r = rename d = delete'), align="center" )
			self.keys = urwid.AttrWrap( self.keys_text, 'keys' )
			self.dir_text = urwid.Text( ('dir', 'DIR GOES HERE'), align="center" )
			self.dir = urwid.AttrWrap( self.dir_text, 'dir' )
			self.files_text = urwid.Text( ('files', 'FILES GO HERE'), align="center" )
			self.files = urwid.AttrWrap( self.files_text, 'files' )
			self.file_text = urwid.Text( ('file', 'FILE GOES HERE'), align="center" )
			self.file = urwid.AttrWrap( self.file_text, 'file' )
			self.suggest_text = urwid.Text( ('suggest', 'FILE GOES HERE'), align="center" )
			self.suggest = urwid.AttrWrap( self.suggest_text, 'suggest' )
			self.warning_text = urwid.Text( ('warning', 'FILE GOES HERE'), align="center" )
			self.warning = urwid.AttrWrap( self.warning_text, 'warning' )
			self.view_text = urwid.Text( ('view', 'VIEW GOES HERE'), align="left" )
			self.view = urwid.AttrWrap( self.view_text, 'view' )
			self.items = [ self.keys, self.stats, self.dir, self.files, self.file, self.suggest, self.warning, self.view ]
			self.listbox = urwid.ListBox( self.items )
			self.header = urwid.AttrWrap( self.banner, 'banner' )
			self.top = urwid.Frame(self.listbox, self.header)


	def main(self):
	
		if self.interactive:
			self.ui = urwid.curses_display.Screen()
			self.ui.register_palette([
				('banner', 'black', 'dark cyan', 'standout'),
				('keys', 'black', 'dark green', 'standout'),
				('stats', 'black', 'dark cyan', 'standout'),
				('dir', 'black', 'dark red', 'standout'),
				('files', 'black', 'dark red', 'standout'),
				('file', 'black', 'light gray', 'standout'),
				('suggest', 'black', 'light gray', 'standout'),
				('warning', 'black', 'dark red', 'standout'),
				('view', 'black', 'dark cyan', 'standout'),
			])
			self.ui.run_wrapper( self.run )
		else:
			self.run()


	def run(self):
	
		if self.interactive:
			self.size = self.ui.get_cols_rows()
		
		for root, dirs, files in os.walk(self.root):

			if self.interactive:
				sizes = map(lambda x: os.path.getsize('%s/%s' % (root, x)), files)
				text = "%s bytes in %s files" % (sum(sizes), len(files))
				self.dir_text.set_text( root )
				self.stats_text.set_text( text )
				self.files_text.set_text( ' '.join(files) )
			
			if len(files):
				for fn in files:
					if self.interactive:
						full_name = "%s/%s" % (root, fn)
						self.file_text.set_text( full_name )
						ret = self.suggest_name( full_name )
						self.suggest_text.set_text( ret[1] )
						self.warning_text.set_text( ret[0] )
						# FIXME: add an edit box
						if ret[0] == '' or not self.skip_broken:
							ret = self.process_events()
							if ret == 'quit':
								return
					else:
						f = "%s/%s" % (root, fn)
						ret =  self.suggest_name(f)
						print("%s: %s %s" % ( ret[0], f, ret[1] ))


	def suggest_name(self, name):
	
		# Read the first line
		f = open( name, 'r' )
		firstline = f.readline()
		f.close()
		warning = ''
		
		# Test if the file contains NUL bytes
		f = open( name, 'rb' )
		d = f.read()
		f.close()
		if d.find('\x00') >= 0:
			warning += 'contains NUL! '
		
		# Check if the first line matches a text or html regex
		m = self.html_regex.match(firstline)
		if m:
			ext = 'html'
			last_line = "\n</body></html>"
			if d[-len(last_line):] != last_line:
				warning += 'malformed html! '
		else:
			ext = 'txt'
			m = self.text_regex.match(firstline)
			if not m:
				return ('no match','')
		
		# Get the matches
		g = list(m.groups())
		if len(g) != 9:
			return ('not enough matches: '+str(len(g)), '')
		
		# Some old files missy the account name
		if g[7] == '':
			# FIXME: distinguish between multiple accounts
			if g[8] == 'icq':
				g[7] = '270582044'
			elif g[8] == 'msn':
				g[7] = 'pabs3@hotmail.com'
			elif g[8] == 'yahoo':
				g[7] = 'pabsness slashdotaccount'
			elif g[8] == 'jabber':
				g[7] = 'pabs@jabber.org pabs@jabber.org.au paul.is.wise@gmail.com'
		
		# Some old files have S in place of seconds
		if g[6] == 'S':
			g[6] = '00'
		
		# Validate the matches
		if g[8] not in ('icq', 'msn', 'yahoo', 'jabber'):
			warning += 'wrong proto: %s ' % g[8]
		if len(g[1]) != 4:
				warning += 'wrong len(4): m1 '
		for i in range(2,6):
			if len(g[i]) != 2:
				warning += 'wrong len(2): m%s ' %i
			
		return (warning, "/home/pabs/.purple/logs/%s/%s/%s/%s-%s-%s.%s%s%s.%s" % ( g[8], g[7], g[0], g[1], g[2], g[3], g[4], g[5], g[6], ext) )


	def process_events(self):
			cont = True
			while cont:
				self.draw_screen( self.size )
				keys = self.ui.get_input()
				if "n" in keys: 
					cont = False
				for k in keys:
					if k == "window resize":
						self.size = self.ui.get_cols_rows()
						continue
					elif k == 'q':
						return 'quit'
					elif k == 'r':
						old = os.path.join( self.dir_text.get_text()[0], self.file_text.get_text()[0] )
						new = self.suggest_text.get_text()[0]
						if os.path.exists( new ):
							os.spawnv(os.P_WAIT, self.compare, [self.compare, old, new])
							#raise NameError, "file exists: meld '%s' '%s'\nrm -f '%s'" % (new, old, old)
						else:
							#raise NameError, 'os.rename %s %s %s %s' % (old, new, os.path.exists(old), os.path.exists(new) )
							try:
								os.makedirs( os.path.dirname( new ) )
							except:
								# We don't care if the new directory is already there
								pass
							os.rename( old, new )
							cont = False
					elif k == 'd':
						old = os.path.join( self.dir_text.get_text()[0], self.file_text.get_text()[0] )
						os.remove( old )
						cont = False
						
					self.top.keypress( self.size, k )


	def draw_screen(self, size):
		canvas = self.top.render( size, focus=True )
		self.ui.draw_screen( size, canvas )


GaimLogRenamer().main()
