"""   QuArK  -  Quake Army Knife

Map editor brush-from-number finder
"""
#
# Copyright (C) 1996-2003 The QuArK community
# THIS FILE IS PROTECTED BY THE GNU GENERAL PUBLIC LICENCE
# FOUND IN FILE "COPYING.TXT"
#

import quarkx
from maputils import *

#
# an exception
#
class CorruptError(Exception):
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return self.msg

def findBrush(editor, address):
    "address is a sequence of BrushAddressNodes"
    current = editor.Root
    for node in address:
        if node.index==0:
            quarkx.helppopup("This brush, named '%s', was generated by a duplicator or negative brush, whose containing group has been selected."%current.name)
            return last
        next = current.subitems[node.index-1]
        if node.name!=next.name:
            error="expected: %s; actual %s"%(node.name, next.name)
            quarkx.msgbox("name discrepancy, "+error,
               MT_ERROR,MB_OK)
        last = current
        current = next
    return current


class BrushNumDlg(SimpleCancelDlgBox):
    #
    # dialog layout
    #
    size = (160, 75)
    dfsep = 0.6
    flags = FWF_KEEPFOCUS

    dlgdef = """
    {
        Style = "9"
        Caption = "Brush Number Dialog"

        brushnum: =
        {
        Txt = "Brush Number:"
        Typ = "EF2"
        Hint = "Enter entity and brush numbers, separated by space, as specified in compile" $0D "tool output (e.g. 0 2).  Brush will be selected on <enter> if possible." $0D "The use of duplicators may create difficulties."
        }
        cancel:py = {Txt="" }
    }
    """

    def __init__(self, form, editor, brushDict):
        src = quarkx.newobj(":")
        self.src = src
        self.editor = editor
        self.brushDict = brushDict
        SimpleCancelDlgBox.__init__(self,form,src)

    def ok(self):
        pass

    def datachange(self, df):
        entity, index = self.src["brushnum"]
        entity, index = int(entity), int(index)
        try:
            address = self.brushDict[(entity,index)]
        except (KeyError):
            quarkx.msgbox("No such brush",MT_ERROR,MB_OK)
            return
        brush = findBrush(self.editor,address)
        self.editor.layout.explorer.sellist = [brush]


class BrushAddressNode:
    ".name, .index (int)"
    def __init__(self, nodeLabel):
        name, index = nodeLabel.split('[')
        self.name = name.strip()
        index = index.strip()
        index = index[:len(index)-1]
        if index:
            self.index = int(index)
        else:
            self.index = 0

def getBrushDict(editor, filename):
    f = open(filename, "r")
    try:
        data = f.readlines()
    finally:
        f.close()
    dict = {}
    commentPrefix=quarkx.setupsubset()["MapCommentsPrefix"]
    commentPrefixLen = len(commentPrefix)
    i = -1
    while 1:
        i=i+1
        if i>=len(data):
            break
        line = data[i]
        if line[:commentPrefixLen]!=commentPrefix:
            continue
        linewords = line.split()
        if linewords[1]=="Entity":
            entity = int(linewords[2])
            brushCount = -1
            continue
        if linewords[1]!="Brush":
            continue
        brushNum = int(linewords[2])
        brushCount = brushCount+1
        if brushNum!=brushCount:
            raise CorruptError("Brush %d"%brushNum)
        i=i+1
        line=data[i]
        if line[:commentPrefixLen]!=commentPrefix:
            quarkx.msgbox('problem with map file at line %d'%i,MT_ERROR,MB_OK)
            continue
        address = line[commentPrefixLen:].split('->')
        address = map(BrushAddressNode, address)
        dict[(entity, brushNum)] = address
    return dict

def LoadBrushNums(editor, filename):
    try:
        brushDict = getBrushDict(editor, filename)
        BrushNumDlg(quarkx.clickform, editor, brushDict)
    except CorruptError, msg:
        quarkx.helppopup("Brush number discrepancy at brush labeled %s; this probably means that the file is corrupt"%msg)
