#!/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, tag_header
from tag_data import localInfo
                    
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 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=tag_header.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=tag_header.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=tag_header.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=tag_header.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()==tag_header.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==tag_header.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 findUnusedTags(self, myLocal, localOnly):    
        #add all of our prel items to one list so we can just to a quick check to see if a tag was loaded.
        meshList=myLocal.getTagList('mesh',localOnly)
        prelList=myLocal.getTagList('prel', localOnly)
        bigList={}
        for prel in prelList:
            for a,b in prel.preload_definition.iteritems():
                if a in bigList:
                    bigList[a].extend(b)
                else:
                    bigList[a]=b
        #Double check to make sure all the mesh tags are listed as used
        for mesh in meshList:
            for tTag, tagType in mesh.getLinkedTags():
                tTag=tag_header.tagCheck(tTag)
                if tagType in bigList:
                    if tTag not in bigList[tagType]:
                        bigList[tagType].append(tTag)
                else:
                    bigList[tagType]=[tTag]
        #go thru all tags and see if they are in bigList
        returnList=[]
        for tagType, tagList in myLocal.tagsDictionary.iteritems():
            if tagType!='prel' and tagType!='bina' and tagType!='ditl' and tagType!='font' and tagType!='dist' and tagType!='inte' and tagType!='temp':
                if tagType in bigList:
                    for tTag in tagList:
                        if tTag.tagHeader.getSubgroup_Tag() not in bigList[tagType]:
                            if tTag.isLocal:
                                returnList.append(tTag)
                else:
                    for tTag in tagList:
                        if tTag.isLocal:
                            returnList.append(tTag)
        return returnList
    
    
    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 effect", "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 tag_header.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)
            