#!/usr/bin/python

__author__ = "Mike Oldham (tarous@gmail.com)"
__version__ = "$Revision: 1.0 $"
__date__ = "$Date: 2005/11/29 00:12:26 $"
__copyright__ = "Copyright (c) 2006 Mike Oldham"
__license__ = "CC"

import os,getopt, sys, struct, shutil
from tag_data import localInfo

class tag_file_header:
	def __init__(self,dFile):
		self.type=struct.unpack(">h", dFile.read(2))[0]
		self.version=struct.unpack(">h", dFile.read(2))[0]
		self.name=dFile.read(32)
		self.name=self.name.rstrip(self.name[-1])
		self.url=dFile.read(64)
		self.url=self.url.rstrip(self.url[-1])
		self.entry_point_count=struct.unpack(">h", dFile.read(2))[0]
		self.tag_count=struct.unpack(">h", dFile.read(2))[0]
		self.checksum=struct.unpack(">L", dFile.read(4))[0]
		self.flags=struct.unpack(">L", dFile.read(4))[0]
		self.size=struct.unpack(">l", dFile.read(4))[0]
		self.header_checksum=struct.unpack(">L", dFile.read(4))[0]
		self.unused=struct.unpack(">l", dFile.read(4))[0]
		self.signature=struct.unpack(">L", dFile.read(4))[0]
		
class Tag_Header:
	"""Default 64 byte tag header for all myth tags."""
	def __init__(self,dFile,dOffset):
		dFile.seek(dOffset)
		self.Identifier=struct.unpack(">h", dFile.read(2))[0]
		self.flags=struct.unpack("c", dFile.read(1))[0]
		self.type=struct.unpack("c", dFile.read(1))[0]
		self.name=dFile.read(32)
		self.name=self.name.rstrip(self.name[-1])
		self.group_tag=dFile.read(4)
		self.subgroup_tag=dFile.read(4)     #aka 4 byte tag ID
		tmpData=dFile.read(4)
		self.offset=struct.unpack(">i", tmpData)[0]
		self.size=struct.unpack(">l", dFile.read(4))[0]
		self.user_data=struct.unpack(">L", dFile.read(4))[0]
		self.version=struct.unpack(">h", dFile.read(2))[0]
		self.destination=struct.unpack("c", dFile.read(1))[0]
		self.owner_index=struct.unpack("c", dFile.read(1))[0]
		self.game_version=dFile.read(4)
		self.tagType=0
	def setTagType(self, theType): self.tagType=theType
	def getTagType(self): return self.tagType
	def getOffset(self): return self.offset
	def getName(self): return self.name
	def getGroup_Tag(self): return self.group_tag
	def getSubgroup_Tag(self): return self.subgroup_tag
	def getID(self): return self.subgroup_tag
	def getOffset(self): return self.offset						
						
					

class mythTags:	
	def __init__(self):	
		self.neg1=65535
		
	def getTagByCode(self, theCode, theList):
		for theTag in theList:
			if theTag.tagHeader.getSubgroup_Tag()==theCode:
				return theTag
		return "None"
	
			
	def tagCheck(self, theTag):
		if struct.pack(">L", theTag)==struct.pack(">L",-1):
			return "None"
		else:
			return struct.pack(">L", theTag)
			
	
	def PrintPRGRandPROJ(self, myLocal,isLocalOnly):
		prgrList=myLocal.getTagList('prgr', False)
		projList=myLocal.getTagList('proj', False)
		lpgrList=myLocal.getTagList('lpgr', False)
		sounList=myLocal.getTagList('soun', False)
		meefList=myLocal.getTagList('meef', False)
		prgrStringArray= []
		for i in range(len(prgrList)):
			tmpString=""
			myPrgr=prgrList[i]
			if isLocalOnly:
				if myPrgr.isLocal:
					doContinue=True
				else:
					doContinue=False
			else: 
				doContinue=True
			if doContinue:
				tmpString=tmpString + myPrgr.getPRGRName() + " (" + myPrgr.getPRGRCode() + ")\n"
				meefCode=self.tagCheck(myPrgr.mesh_effect_tag)
				meefName=""
				if meefCode !="None":
					meefTag=self.getTagByCode(meefCode,meefList)
					if meefTag !="None":
						meefName=meefTag.tagHeader.getName()
				tmpString=tmpString + "  --mesh effect: " + meefName + " (" + meefCode + ")\n"
				sounCode=self.tagCheck(myPrgr.sound_tag)
				sounName=""
				if sounCode !="None":
					sounTag=self.getTagByCode(sounCode,sounList)
					if sounTag !="None":
						sounName=sounTag.tagHeader.getName()
				tmpString=tmpString + "  --Sound: " + sounName + " (" + sounCode + ")\n"
				lpgrCode=self.tagCheck(myPrgr.local_projectile_group_tag)
				lpgrName=""
				if lpgrCode !="None":
					lpgrTag=self.getTagByCode(lpgrCode,lpgrList)
					if lpgrTag !="None":
						lpgrName=lpgrTag.tagHeader.getName()
				
				tmpString=tmpString + "  --Local Projectile group: " + lpgrName + " (" + lpgrCode + ")\n"
				
				prgrProjList=myPrgr.getPROJList()
				for j in range(len(prgrProjList)):
					myProjDef=prgrProjList[j]
					for k in range(len(projList)):
						myProj=projList[k]
						if myProj.getPROJCode()==myProjDef.getPROJCode():
							tmpString=tmpString + "  --" + myProj.getPROJName() + \
							"(" + myProjDef.getPROJCode() + ")\n"
							tmpString=tmpString + "        count: " +  str(myProjDef.count_lower_bound) + \
							" to " +  str(myProjDef.getCountUpperBound()) + "\n"
							tmpString=tmpString + "        position: " +  str(myProjDef.getPositionLowerBound()) + \
							" to " +  str(myProjDef.getPositionUpperBound()) + "\n"
							tmpString=tmpString + "        appearing fraction: " + \
							str(myProjDef.getAppearingFraction()) + "\n"
							tmpString=tmpString + "        Is central: " +  str(myProjDef.getIsCentral()) + "\n"
							tmpString=tmpString + "        Is on ground: " +  str(myProjDef.getIsOnGround()) + "\n"
							break
				tmpString=tmpString + "\n\n"
			prgrStringArray.append((tmpString, myPrgr.tagHeader.getTagType()))
		return prgrStringArray
	
	def listUnusedProjectiles(self, myLocal,isLocalOnly):
		mondoProjList=[]
		mondoProjList.append(myLocal.getTagList('mons', False))
		mondoProjList.append(myLocal.getTagList('prgr', False))
		mondoProjList.append(myLocal.getTagList('scen', False))
		mondoProjList.append(myLocal.getTagList('arti', False))
		myProjList=myLocal.getTagList('proj', False)
		mondoProjList.append(myProjList)
		
		finalProjList={}
		for dProj in myProjList:
			if isLocalOnly:
				if dProj.isLocal:
					finalProjList[dProj.getPROJCode()]=dProj
			else:
				finalProjList[dProj.getPROJCode()]=dProj
		
		for prList in mondoProjList:
			for theItem in prList:
				itemList=theItem.getLinkedTags()
				if itemList !=False:
					for bItem,bType in itemList:
						if bType=='proj':
							bTag=self.tagCheck(bItem)
							if bTag in finalProjList:
								del finalProjList[bTag]
								
		theStringArray=[]
		theStringArray.append(("The Following Projectiles are Unused:\n", 0))
		realFinal=[]
		for i in range(len(finalProjList)):
			tmpItem=finalProjList.popitem()
			theStringArray.append(((str(i)+": " + tmpItem[1].getPROJName() + " (" + tmpItem[0] + ")" + "\n"), tmpItem[1].tagHeader.getTagType()))
		return theStringArray
			
			
	def listByDamageType(self,dItem,dList,myLocal,isLocalOnly):
		projList=myLocal.getTagList('proj', False)
		dOffset=self.neg1
		for i in range(len(dList)):
			if dList[i]==dList[dItem]:
				dOffset = i-1
				if dOffset<0:
					dOffset=self.neg1
				break
		projStringArray=[]
		projStringArray.append(("The Following Projectiles do " + dList[dItem] + " Damage: \n", 0))
		for i in range(len(projList)):
			myProj=projList[i]
			if isLocalOnly:
				if myProj.isLocal:
					doContinue=True
				else:
					doContinue=False
			else: 
				doContinue=True
			if doContinue:
				if myProj.damage.type==dOffset:
					projStringArray.append((myProj.getPROJName() + "\n", myProj.tagHeader.getTagType()))
		return projStringArray
		
	def listByInertiaType(self,dItem,dList,myLocal,isLocalOnly):
		projList=myLocal.getTagList('proj', False)
		dOffset=self.neg1
		for i in range(len(dList)):
			if dList[i]==dList[dItem]:
				dOffset = i-1
				break
		projStringArray=[]
		projStringArray.append(("The Following Projectiles have " + dList[dItem] + " Inertia: \n", 0))
		for i in range(len(projList)):
			myProj=projList[i]
			if isLocalOnly:
				if myProj.isLocal:
					doContinue=True
				else:
					doContinue=False
			else: 
				doContinue=True
			if doContinue:
				if myProj.getInertiaType()==dOffset:
					projStringArray.append((myProj.getPROJName() + "\n", myProj.tagHeader.getTagType()))
		return projStringArray
		
	def listByClassType(self,dItem,dList,myLocal,isLocalOnly):
		projList=myLocal.getTagList('proj', False)
		dOffset=self.neg1
		for i in range(len(dList)):
			if dList[i]==dList[dItem]:
				dOffset = i-1
				if dOffset<0:
					dOffset=self.neg1
				break
		projStringArray=[]
		projStringArray.append(("The Following Projectiles have the " + dList[dItem] + " Class: \n", 0))
		for i in range(len(projList)):
			myProj=projList[i]
			if isLocalOnly:
				if myProj.isLocal:
					doContinue=True
				else:
					doContinue=False
			else: 
				doContinue=True
			if doContinue:
				if myProj.getClassType()==dOffset:
					projStringArray.append((myProj.getPROJName() + "\n", myProj.tagHeader.getTagType()))
		return projStringArray
	
	def findAllDeadMonsters(self,myLocal, localOnly):
		monsList=myLocal.getTagList('mons', localOnly)
		unitList=myLocal.getTagList('unit', False)
		tagStringArray= []
		if self.findAllDeadMonsters:
			noTags=0
			for i in range(len(monsList)):
				myMons=monsList[i]
				for j in range(len(unitList)):
					myUnit=unitList[j]
					if myMons.getmCode()==self.tagCheck(myUnit.getMONSCode()):
						myMons.setuID(j)
						j=len(unitList)
				if (myMons.getuID()==-1) and True: #(myMons.getIsLocal()):
					if noTags==0:
						tmpString= "The Following Monster Tags have no linking Unit Tags:\n"
						tagStringArray.append((tmpString, 0))
						noTags=noTags+1
					tmpString="MONS Name: " + monsList[i].getmName() + "\n"
					tmpString=tmpString+ "    MONS Code: " + monsList[i].getmCode() + "\n"
					tagStringArray.append((tmpString, monsList[i].tagHeader.getTagType()))
		if noTags==0:
			tmpString="Congratulations All Monster Tags have a linking Unit Tag!"
			tagStringArray.append((tmpString, 0))
		return tagStringArray
				
	def findMonsByName(self,searchMonster,myLocal):
		monsList=myLocal.getTagList('mons', False)
		for dMons in monsList:
			if str(searchMonster)==str(dMons.getmName()):
				return self.findMonsByTag(dMons.getmCode(),myLocal)
		tmpString="Couldn't find a Monster with that name"
		return [(tmpString, 0)]	
		
	def findMonsByTag(self,searchMonster,myLocal):
		tagStringArray= []
		unitList=myLocal.getTagList('unit', False)
		myMonsUnitList=[]
		for j in range(len(unitList)):
			myUnit=unitList[j]
			if searchMonster==self.tagCheck(myUnit.getMONSCode()):
				myMonsUnitList.append(myUnit)
		if len(myMonsUnitList)>0:
			for dUnit in myMonsUnitList:
				tmpString="Unit Name: " + dUnit.getUNITName()
				tmpString=tmpString+ "    Unit Code: " + dUnit.getUNITCode() + "\n"
				tagStringArray.append((tmpString, dUnit.tagHeader.getTagType()))
		else:
			tmpString="You wanted to find " + searchMonster + ". It's a pity I couldn't find it."
			tagStringArray.append((tmpString, 0))
		return tagStringArray
		
	def findDuplicateObjects(self, myLocal,isLocalOnly):
		tagStringArray= []
		objeList=myLocal.getTagList('obje', isLocalOnly)
		tmpList = []
		usedList=[]
		for tmpObject in objeList:
			tmpList.append(tmpObject)
		while len(tmpList)>0:
			dObject = tmpList.pop(0)
			if dObject not in usedList:
				firstPass=True
				for bObject in tmpList:
					if dObject.compareData(bObject):
						if firstPass:
							firstPass=False
							tmpString=dObject.tagHeader.getName() + "(" + dObject.tagHeader.getSubgroup_Tag() + ")\n"
							tagStringArray.append((tmpString, dObject.tagHeader.getTagType()))
						tmpString= "    " + bObject.tagHeader.getName() + "(" + bObject.tagHeader.getSubgroup_Tag() + ")\n"
						tagStringArray.append((tmpString, bObject.tagHeader.getTagType()))
						usedList.append(bObject)
		return tagStringArray

	def copyFile(self, srcFile, dstFile):
		fin = open(srcFile, "rb")   # notice the 'rb'
		fout = open(dstFile, "wb")  # ...and the 'wb'
		data = fin.read(1000)        # or any amount of bytes you want to read
		while data:
			fout.write(data)
			data = fin.read(1000)
		fin.close()
		fout.close()
	
	def getTagPath(self, theTag, chaosPath):
		self.folderList={"arti":"artifacts", ".256":"collections", "core":"collection references", "ligh":"lightning", "lpgr":"local projectile groups", "meef":"mesh effects", "mons":"monsters", "obje":"objects", "phys":"local physics", "prgr":"projectile groups", "proj":"projectiles", "scen":"scenery", "soun": "sounds", "stli":"string lists", "unit":"units"}
		folderPath=chaosPath +  self.folderList[theTag.tagHeader.getGroup_Tag()]
		if os.path.isdir(folderPath)==False:
			os.mkdir(folderPath)
		return folderPath + "/" + theTag.tagHeader.getName()
		
		
	def ExportLinkedTags(self, theLocal, theTag):
		thisDictionary = {}
		tagType=theTag.tagHeader.getGroup_Tag()
		thisDictionary[tagType]=[]
		thisDictionary[tagType].append(theTag)
		self.getLinkedTags(thisDictionary, theLocal, theTag)
		chaosPath=theLocal.chaosLocalPath
		if os.path.isdir(chaosPath):
			shutil.rmtree(chaosPath)
		os.mkdir(chaosPath)
		for theList in thisDictionary.itervalues():
			for theTag in theList:
				if theTag.tagHeader.getTagType()==1:
					newPath=self.getTagPath(theTag, chaosPath)
					shutil.copyfile(theTag.fPath, newPath)
		

	def getLinkedTags(self, tagsDictionary, myLocal, startTag):
		linkedResult=startTag.getLinkedTags()
		if linkedResult!=False:
			for linkedItem in linkedResult:
				tmpList=myLocal.getTagList(linkedItem[1], False)
				daTag=False
				for tmpTag in tmpList:
					if self.tagCheck(linkedItem[0])==tmpTag.tagHeader.getSubgroup_Tag():
						daTag=tmpTag
						break
				if daTag!=False:
					#linkedTags.append(daTag)
					tagType=daTag.tagHeader.getGroup_Tag()
					if tagType not in tagsDictionary:
						tagsDictionary[tagType]=[]
					if daTag not in tagsDictionary[tagType]:
						tagsDictionary[tagType].append(daTag)
						self.getLinkedTags(tagsDictionary, myLocal,daTag)
			