from inc_noesis import *
import noesis
import rapi
from Sanae3D.Sanae import SanaeObject

def registerNoesisTypes():
    '''Register the plugin. Just change the Game name and extension.'''
    
    handle = noesis.register("Guild Wars", ".raw")
    noesis.setHandlerTypeCheck(handle, noepyCheckType)
    noesis.setHandlerLoadModel(handle, noepyLoadModel)
    return 1

def noepyCheckType(data):
    '''Verify that the format is supported by this plugin. Default yes'''
    
    return 1

def noepyLoadModel(data, mdlList):
    '''Build the model, set materials, bones, and animations. You do not
    need all of them as long as they are empty lists (they are by default)'''
    
    ctx = rapi.rpgCreateContext()
    parser = SanaeParser(data)
    parser.parse_file()
    mdl = rapi.rpgConstructModel()
    mdl.setModelMaterials(NoeModelMaterials(parser.texList, parser.matList))
    mdl.setBones(parser.boneList)
    mdl.setAnims(parser.animList)
    mdlList.append(mdl)
    return 1

class SanaeParser(SanaeObject):
    
    def __init__(self, data):    
        '''Initialize some data. Refer to Sanae.py to see what is already
        initialized'''
        
        super(SanaeParser, self).__init__(data)
        self.fileFlags = []
        self.meshFlags = []
        
    def parse_faces(self, numIdx):
        
        return self.inFile.readBytes(2*numIdx)
    
    def parse_vertices(self, numVerts, vertType):
        
        if vertType == 0x15:
            vertBuff = self.inFile.readBytes(numVerts*32)
            rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 0)
            rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 12)
            rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 24)
        if vertType == 0x17:
            vertBuff = self.inFile.readBytes(numVerts*36)
            rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 0)
            rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 16)
            rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 28)        
        elif vertType == 0x35:
            vertBuff = self.inFile.readBytes(numVerts*40)
            rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 40, 0)
            rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 40, 12)
            rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 40, 32)
        elif vertType == 0x3075:
            vertBuff = self.inFile.readBytes(numVerts*72)
            rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 72, 0)
            rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 72, 12)
            rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 72, 64)
        elif vertType == 0x30F5:
            vertBuff = self.inFile.readBytes(numVerts*80)
            rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 80, 0)
            rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 80, 12)
            rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 80, 72)            
                    
        self.plot_points(numVerts)
        
    def parse_mesh(self, numMesh):
        
        face1, face2, face3 = self.inFile.read('3L')
        if face1 != face2 or face1 != face3 or face2 != face3:
            numIdx = sum([face1, face2, face3])
        else:
            numIdx = face1
        numVerts = self.inFile.readUInt()
        vertType = self.inFile.readUInt()
        unk1, unk2, unk3 = self.inFile.read('3L')
        meshUnks = [unk1, unk2, unk3]
        
        print(numIdx, numVerts, vertType)
        print(self.inFile.tell())
        idxBuff = self.parse_faces(numIdx)
        print(self.inFile.tell())
        self.parse_vertices(numVerts, vertType)
        
        rapi.rpgCommitTriangles(idxBuff, noesis.RPGEODATA_USHORT, numIdx, noesis.RPGEO_TRIANGLE, 1)
        
    def parse_mesh_info(self, numMesh):
        
        print(numMesh)
        if numMesh == 1:
            fileFlags = self.fileFlags[2]
            flags = self.meshFlags[0]
            print(fileFlags)
            print(flags)
            if flags[7] == 0:
                self.inFile.readUByte()
                self.inFile.read('2B' * flags[6])
                self.inFile.read('B' * fileFlags[9])
                self.inFile.read('L' * fileFlags[12])
                self.inFile.read('L' * fileFlags[10]*2)
            elif flags[7] == 1:
                self.inFile.readUShort()
                self.inFile.readUInt()
                self.inFile.readUShort()
                self.inFile.readUByte()
                print(self.inFile.tell())
                if fileFlags[12] == 1:
                    self.inFile.readUByte()
            elif flags[7] == 2:
                self.inFile.readUInt()
                self.inFile.readUShort()
                self.inFile.read('2L')
                self.inFile.read('2H')
                if fileFlags[12] == 1:
                    self.inFile.readUShort()
        else:
            print(numMesh)
        self.inFile.readUInt()
        
    def parse_file(self):
        '''Main parser method'''
        
        #header
        idstring = self.read_string(4)
        model = self.inFile.readUByte()
        fileType = self.inFile.readUInt()
        filesize = self.inFile.readUInt()
        self.inFile.read('2L')
        
        unk1, unk2 = self.inFile.read('2B')
        unk3 = self.inFile.read('2B')
        type1 = self.inFile.readUInt()
        type2 = self.inFile.readUInt()
        fileFlags = self.inFile.read('20b')
        self.fileFlags = [type1, type2, fileFlags]
        
        scale1, scale2 = self.inFile.read('2f')
        self.inFile.read('20B')
        numMesh = self.inFile.readUByte()
        if not numMesh:
            pass
        else:
            self.inFile.read('15b')
            
        if unk1 in [12, 42]:
            numMesh += fileFlags[8]
        
        for i in range(numMesh):
            self.meshFlags.append(self.inFile.read('8b'))
            
        if numMesh:
            print(self.inFile.tell())
            self.parse_mesh_info(numMesh)
            print(self.inFile.tell())
            self.parse_mesh(numMesh)