"""
DataHandler-modul, har ansvar for å instansiere riktig klasse
etter hva brukeren ønsker å bruke som lagringsmedium.

2002-05-22 - Mats Lindh
"""


import Image, string, os, xml.dom.minidom

##################
# class DataHandler
# 	- generell klasse som implementeres i de ulike presentasjonsmodulene.
#	  sørger for transparent kobling overfor de ulike undermodulene.
##################

class DataHandler:
	##################
	# __init__(scheme, file = "")
	# 	- generell klasse som implementeres i de ulike presentasjonsmodulene.
	#	  sørger for transparent kobling overfor de ulike undermodulene.
	#
	#	scheme:	hvilken handler som skal brukes ('xml', 'inline', 'flat')
	#	file:	hvilken fil som skal brukes for å lagre informasjonen (eller path til inline-tools (wrjpgcom/rdjpgcom)
	##################
	def __init__(self, scheme, file = ""):		
		self.handler = None
		
		if (string.lower(scheme) == "xml"):
			# lasting fra xml ..
			self.handler = DataHandlerXML(file)
			
		elif (string.lower(scheme) == "inline"):
			# kommentarer i selve filene.. (file er PATH til rdjpgcom/wrjpgcom)
			self.handler = DataHandlerINLINE(file)
		
		elif (string.lower(scheme) == "flat"):
			# .. flat tekstfil
			self.handler = DataHandlerFLAT(file)
			
		else:
			# hvis ingen av de tre metodene, så raiser vi en egen, liten exception for det..
			raise ValueError, 'invalid module-name for DataHandler'

	##################
	# get_data(file)
	#	- henter ut informasjon om angitt fil.
	#
	#	file:	filnavnet man skal ha informasjon om.
	##################
				
	def get_data(self, file):
		return self.handler.get_data(file)

	##################
	# set_data(file, beskrivelse, kategori, sted, dato, fotograf)
	#	- lagrer informasjon om angitt fil.
	#
	#	file:	filnavnet man skal ha informasjon om.
	#	beskrivelse:	beskrivelse av bildet
	#	kategori:	kategori som bildet tilhører
	#	sted:	sted bildet er tatt
	#	dato:	dato bildet er tatt
	#	fotograf:	hvem som har tatt bildet
	##################
		
	def set_data(self, file, beskrivelse, kategori, sted, dato, fotograf):
		# lager et objekt for dataene som skal settes og kaller handler-metoden.
		d = ImageData(os.path.basename(file), beskrivelse, kategori, sted, dato, fotograf)
		self.handler.set_data(file, d)

	##################
	# destroy()
	#	- avslutter den gjeldende handleren (rydder opp)
	##################

	def destroy(self):
		self.handler.destroy()

	##################
	# write(fnavn = "")
	#	- gir beskjed til handleren om at informasjonen som er i minnet skal lagres.
	#
	#	fnavn:	filnavn som det skal lagres til. Hvis ikke angitt, lagring til samme sted som det ble lastet.
	##################

	def write(self, fnavn = ""):
		self.handler.write(fnavn)

##################
# class DataHandlerINLINE
# 	- handler for data i XML-filer.
##################

class DataHandlerXML:
	##################
	# __init__(file)
	# 	- initialiserer XML-handleren
	#
	#	file:	xml-filen som data skal leses fra / lagres til.
	##################

	def __init__(self, file):
		#print ("XML-handler started for " + file)
		self.data = []
		self.file = file
		
		if (os.path.isfile(self.file)):
			# lager et dom-tre fra xml-filen
			dom = xml.dom.minidom.parseString(open(self.file).read())
			dom.normalize()
			
			# leser inn informasjonen fra DOM-treet
			for element in dom.getElementsByTagName("image"):
				fnavn = string.strip(element.getElementsByTagName("file")[0].childNodes.item(0).data).encode("iso-8859-1")
				beskrivelse = string.strip(element.getElementsByTagName("beskrivelse")[0].childNodes.item(0).data).encode("iso-8859-1")
				kategori = string.strip(element.getElementsByTagName("kategori")[0].childNodes.item(0).data).encode("iso-8859-1")
				sted = string.strip(element.getElementsByTagName("sted")[0].childNodes.item(0).data).encode("iso-8859-1")
				dato = string.strip(element.getElementsByTagName("dato")[0].childNodes.item(0).data).encode("iso-8859-1")
				fotograf = string.strip(element.getElementsByTagName("fotograf")[0].childNodes.item(0).data).encode("iso-8859-1")
				self.data.append(ImageData(fnavn, beskrivelse, kategori, sted, dato, fotograf))
			
	def get_data(self, file):
		file = os.path.basename(file)
			
		# finner riktig informasjon i samlingen..
		for fil in self.data:
			if (fil.filnavn == file):
				return fil
				
		return None
		
	def set_data(self, file, data):
		hit = 0
		
		for fil in self.data:
			# hvis bildet finnes i samlingen fra før, oppdaterer vi informasjonen vi har lagret om det..
			if (fil.filnavn == os.path.basename(file)):
				fil.beskrivelse = data.beskrivelse
				fil.kategori = data.kategori
				fil.sted = data.sted
				fil.dato = data.dato
				fil.fotograf = data.fotograf
				
				hit = 1
				
		if (hit == 0):
			# bildet finnes ikke fra før, så vi legger det til..
			self.data.append(data)
	
	def destroy(self):
		#fjerner data..
		self.data = []
	
	def write(self, fnavn = ""):
		# åpner fil for skriving..
		if (fnavn == ""):
			file = open(self.file, "w")
		else:
			file = open(fnavn, "w")

		
		# skriver xml-headeren til fil..
		file.write("""<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE nyheter SYSTEM "imageCollection.dtd">
<imageCollection>
""")
		# skriver alle postene til fil..
		for fil in self.data:
			file.write("\t<image>\n")
			file.write("\t\t<file>\n\t\t\t" + fil.filnavn + "\n\t\t</file>\n")
			file.write("\t\t<beskrivelse>\n\t\t\t" + fil.beskrivelse + "\n\t\t</beskrivelse>\n")
			file.write("\t\t<kategori>\n\t\t\t" + fil.kategori + "\n\t\t</kategori>\n")
			file.write("\t\t<sted>\n\t\t\t" + fil.sted + "\n\t\t</sted>\n")
			file.write("\t\t<dato>\n\t\t\t" + fil.dato + "\n\t\t</dato>\n")
			file.write("\t\t<fotograf>\n\t\t\t" + fil.fotograf + "\n\t\t</fotograf>\n")
			file.write("\t</image>\n")

		# avslutter xml-fila
		file.write("</imageCollection>")
		


##################
# class DataHandlerINLINE
# 	- handler for data inline i jpeg-filer
##################

class DataHandlerINLINE:
	##################
	# __init__(path)
	# 	- initialiserer INLINE-handleren
	#
	#	path:	hvor wrjpgcom og rdjpgcom befinner seg
	##################

	def __init__(self, path):
		# path til rdjpgcom
		self.path = path
		
		#print ("INLINE-handler started.")
		return
		
	def get_data(self, file):
		# åpner en prosess mot rdjpgcom..
		jpg = os.popen(self.path + "rdjpgcom.exe " + file, "r")
		# leser inn hva rdjpgcom ga oss..
		tekst = jpg.read()
		jpg.close()
		
		# fikser norske særtegn..
		tekst = string.replace(tekst[:-1], "\\346", "æ")
		tekst = string.replace(tekst, "\\370", "ø")
		tekst = string.replace(tekst, "\\345", "å")

		tekst = string.replace(tekst, "\\306", "Æ")
		tekst = string.replace(tekst, "\\330", "Ø")
		tekst = string.replace(tekst, "\\305", "Å")
		
		# fjerner \030 på slutten av teksten (fra lagring)
		tekst = string.replace(tekst, "\\030", "")
		
		# splitter opp
		poster = string.split(tekst, "\\031")

		# hvis vi har under 5 poster, så er det noe rart på gang, men vi tar vare på kommentaren om det er fra tidligere.
		if (len(poster) < 5):
			if (len(tekst) > 0):
				return ImageData(os.path.basename(file), tekst, "", "", "", "")
			else:
				return None
		
		# returnerer fint objekt med riktige egenskaper.
		return ImageData(os.path.basename(file), poster[0], poster[1], poster[2], poster[3], poster[4])
		
	def set_data(self, file, data):
		# lagrer informasjon til fil..
		tekst = data.beskrivelse + "\031" + data.kategori + "\031" + data.sted + "\031" + data.dato + "\031" + data.fotograf + "\030"
		jpg = os.popen(self.path + "wrjpgcom " + file + " >TMP.JPG", "w")
		jpg.write(tekst)
		jpg.close()

		# henter informasjon om TMP-fila..
		st = os.stat("TMP.JPG")
		if (st.st_size > 0):
			# hvis ikke TMP-fila er 0 i størrelse, så tar vi sjansen på at ting gikk bra..
			os.remove(file)
			os.rename("TMP.JPG", file)
		else:
			# .. hvis ikke, sletter vi bare TMP-fila.
			os.remove("TMP.JPG")
		
	def write(self, fnavn=''):
		# dummy-metode .. oppdatering gjøres real-time når det gjelder inline.
		return

##################
# class DataHandlerFLAT
# 	- handler for data i flat tekst-filer
##################
class DataHandlerFLAT:
	##################
	# __init__(file)
	# 	- initialiserer FLAT-handleren
	#
	#	file:	filen som data skal leses fra / lagres til.
	##################

	def __init__(self, file):
		#print ("FLAT-handler started for " + file)
		self.file = file
		self.data = []
		
		# leser inn informasjon fra filen, dersom den eksisterer.
		if (os.path.isfile(self.file)):
			fil = open(self.file).read()
			
			for post in string.split(fil, "\030"):
				poster = string.split(post, "\031")
				if (len(poster) == 6):
					# legger til data i intern-registeret.
					self.data.append(ImageData(poster[0], poster[1], poster[2], poster[3], poster[4], poster[5]))		
		
	def get_data(self, file):
		# henter ut informasjon fra intern-registeret.
		file = os.path.basename(file)
			
		for fil in self.data:
			if (fil.filnavn == file):
				return fil
				
		return None
		
	def set_data(self, file, data):
		hit = 0
		
		# samme som i XML-handleren, setter egenskapene hos objektet det er snakk om.
		
		for fil in self.data:
			if (fil.filnavn == os.path.basename(file)):
				fil.beskrivelse = data.beskrivelse
				fil.kategori = data.kategori
				fil.sted = data.sted
				fil.dato = data.dato
				fil.fotograf = data.fotograf
				
				hit = 1
				
		if (hit == 0):
			self.data.append(data)

	def destroy(self):
		self.data = []

	def write(self, fnavn = ""):
		if (fnavn == ""):
			file = open(self.file, "w")
		else:
			file = open(fnavn, "w")
		
		# lagrer dataene i minnet til fil, bruker ascii-tegnet med verdi 31 til skille (end of unit) og 30 til å skille mellom poster (end of record)
		
		for fil in self.data:
			file.write(fil.filnavn + "\031" + fil.beskrivelse + "\031" + fil.kategori + "\031" + fil.sted + "\031" + fil.dato + "\031" + fil.fotograf + "\030\n")
		
		file.close()

##################
# class ImageData
# 	- klasse for lagring av informasjon om et bilde
##################

class ImageData:
	##################
	# __init__(filnavn, beskrivelse, kategori, sted, dato, fotograf)
	# 	- initierer objektet med de verdiene man ønsker
	#
	#	filnavn:	navnet på filen
	#	beskrivelse:	beskrivelse av bildet
	#	kategori:	kategori bildet tilhører
	#	sted:	sted bildet er tatt
	#	dato:	dato bildet er tatt
	#	fotograf:	hvem som har tatt bildet
	##################
	def __init__(self, filnavn, beskrivelse, kategori, sted, dato, fotograf):
		self.filnavn = filnavn
		self.kategori = kategori
		self.sted = sted
		self.dato = dato
		self.fotograf = fotograf
		self.beskrivelse = beskrivelse