import os
import time
import pickle

from IO_path import readInitPath

from PyQt4 import QtGui
from PyQt4 import QtCore

from utils import LogW
from utils.ErrorStr import ErrorStr
import subprocess

SCRIPT_PATH = os.path.dirname(os.path.dirname(__file__)) + "\\_pytmp"
DARK_STYLE = os.path.dirname(os.path.dirname(__file__)) + "\\dark.style"
ICON_PATH = os.path.dirname(os.path.dirname(__file__)) + "\\icons"

def loadHip(hip_path, output, UI_PROPERTIES):
    '''
        Load a hip file and return a dictionary of "renderNode" : node.path().
        according to "RENDER_NODES_TYPE"
    '''
    
    # Create python script
    createHouReadScript(hip_path)
    
    # Execute it
    houPath = readInitPath()["HOUDINI_PATH"] + "\\bin\\hython.exe"
    if not os.path.exists(SCRIPT_PATH): os.mkdir(SCRIPT_PATH)
    script = SCRIPT_PATH + "\\tmpread_hip.py"
    p = subprocess.Popen([houPath, script])
    p.wait()
    
    # Fetch dic data
    pickleData =SCRIPT_PATH + "\\tmpread_hou_nodes.out"
    with open(pickleData, 'rb') as handle:
        render_nodes = pickle.load(handle)
        
    # Clean datas if menu switch is True
    if UI_PROPERTIES["clean_py"]:
        cleanHouScript()
    
    return render_nodes

def createHouReadScript(hip_path):
    '''
        Generate the python script for reading hip file and fetch render nodes from it.
        Save nodes found dictionary in _pytmp folder.
    '''
    RENDER_NODES_TYPE = ["rop_comp", "rop_geometry", "ifd"] #"mentalray", "rib", "ribarchive", "opengl"
        
    with open(SCRIPT_PATH + "\\tmpread_hip.py", 'w') as py:
        py.write("# AUTOMATICALLY GENERATED PYTHON SCRIPT\n")
        py.write("# GENERATED BY HMAN: " + str(time.ctime() + "\n"))
        py.write("import hou\n")
        py.write("import pickle\n")
        py.write("")
        py.write("RENDER_NODES_TYPE = {0}\n".format(RENDER_NODES_TYPE))
        py.write('hou.hipFile.load("{0}")\n'.format(hip_path))
        py.write("")
        py.write('allNode = hou.node("obj/").allSubChildren() + hou.node("out/").allSubChildren() + hou.node("img/").allSubChildren()\n')
        py.write('allRenderNodes = [n for n in allNode if n.type().name() in RENDER_NODES_TYPE]\n')
        py.write("")
        py.write('renderNodes = {}\n')
        py.write('for i in RENDER_NODES_TYPE:\n')
        py.write('    renderNodes[i] = [n.path() for n in allRenderNodes if n.type().name() == i]\n')
        py.write('if renderNodes.has_key("ifd"):\n')
        py.write('    tmp = []\n')
        py.write('    for n in renderNodes["ifd"]:\n')
        py.write('        x = hou.node(n).parm("vm_samplesx").eval()\n')
        py.write('        y = hou.node(n).parm("vm_samplesy").eval()\n')
        py.write('        tmp.append([n, [x, y]])\n')
        py.write('        renderNodes["ifd"] = tmp\n')
        py.write("")
        py.write('with open("{0}" + "\\\\tmpread_hou_nodes.out", "wb") as f:\n'.format(SCRIPT_PATH))
        py.write('    pickle.dump(renderNodes, f)')
        
def cleanHouScript():
    '''
        Delete all generated datas from pytmp folder.
    '''
    if not os.path.exists(SCRIPT_PATH): os.mkdir(SCRIPT_PATH)
    
    tmpread_hip = SCRIPT_PATH + "\\tmpread_hip.py"
    tmpread_out = SCRIPT_PATH + "\\tmpread_hou_nodes.out"
    
    if os.path.exists(tmpread_hip):
        os.remove(tmpread_hip)
        
    if os.path.exists(tmpread_out):
        os.remove(tmpread_out)

class PickHouNode(QtGui.QDialog):
    
    def __init__(self, hip_path, inTime, output, UI_PROPERTIES, parent=None):
        QtGui.QDialog.__init__(self, parent=parent)
        
        with open(DARK_STYLE,"r") as style:
            self.setStyleSheet(style.read())
            
        self.setWindowTitle("Pick houdini render node")
        self.setWindowIcon(QtGui.QIcon(ICON_PATH + "\\houdini.png"))
        
        self.UI_PROPERTIES = UI_PROPERTIES
        self.OUT_NODE = None
        
        self.output = output
        
        self.nodes = loadHip(hip_path, output, self.UI_PROPERTIES)

        if self.nodes:
            LogW.writeLog(output.output, ErrorStr.INFO + "Hip file: '{0}' read in {1:0.1f} seconds.".format(hip_path.split("/")[-1],
                                                                                                time.time()-inTime))
        
        self.SELECTED_NODE = None
        self.SELECTED_NODE_TYPE = None
        self.SELECTED_PIXEL_SAMPLE = None
        
        # Fetch pixel sample if any
        self.pixelSample = []
        if self.nodes:
            if "ifd" in self.nodes.keys():
                if self.nodes["ifd"]:
                    self.pixelSample = [n[1] for n in self.nodes["ifd"][0]]
                
        #import hou
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.setAlignment(QtCore.Qt.AlignTop)
        self.mainLayout.setSpacing(10)
        
        btnLayout = QtGui.QHBoxLayout()
        btnLayout.setSpacing(15)
        btnLayout.setAlignment(QtCore.Qt.AlignHCenter)
        
        self.OK = QtGui.QPushButton("Ok")
        self.OK.setFixedWidth(150)
        self.OK.clicked.connect(self.confirmNode)
        self.OK.setObjectName("pushbutton")
        
        btnLayout.addWidget(self.OK)
        
        # Check if any nodes are found
        found = False
        if not self.nodes:
            found = False
        else:
            for k in self.nodes.keys():
                if self.nodes[k]:
                    found = True
                    break
        
        if not found:
            self.nodeNotFoundLabel = QtGui.QLabel("Render nodes not found in the file:\n" + hip_path)
            self.mainLayout.addWidget(self.nodeNotFoundLabel)
            self.setWindowTitle("Error")
            LogW.writeLog(self.output, ErrorStr.ERROR + "Render nodes not found in the file: " + hip_path)
            
        else:
            self.menuLayout = QtGui.QHBoxLayout()
            self.menuLayout.setSpacing(10)
            
            self.mainLayout.addWidget(QtGui.QLabel("Pick a node:"))
            
            self.menuList = []
            
            for k in self.nodes.keys():
                if self.nodes[k]:
                    self._addMenu(k, self.nodes[k])
            
            self.mainLayout.addItem(self.menuLayout)
        
            self.CANCEL = QtGui.QPushButton("Cancel")
            self.CANCEL.setFixedWidth(150)
            self.CANCEL.clicked.connect(self.cancelNode)
            btnLayout.addWidget(self.CANCEL)
            self.CANCEL.setObjectName("pushbutton")
        
        self.mainLayout.addItem(btnLayout)
        
        self.setLayout(self.mainLayout)
            
    def _addMenu(self, node_type, node_list):
        
        menu = NodesMenu(node_type, node_list, self)
        self.menuLayout.addItem(menu)
        self.menuList.append(menu)
    
    def _nodesNotFound(self):
        '''
            Show UI when nodes are not found
        '''
    
    def confirmNode(self):
        
        if self.pixelSample:
            for i in self.nodes["ifd"]:
                if i[0] == self.SELECTED_NODE:
                    self.SELECTED_PIXEL_SAMPLE = i[1]
                    break
            
        self.close()
    
    def cancelNode(self):
        self.SELECTED_NODE = None
        self.SELECTED_NODE_TYPE = None
        self.close()

class NodesMenu(QtGui.QVBoxLayout):
    '''
        Menu which gathers nodes fetched from hip files.
    '''
    
    def __init__(self, node_type, node_list, pickNodeUi, parent=None):
        
        QtGui.QVBoxLayout.__init__(self)
        self.pickNodeUi = pickNodeUi
        
        self.setAlignment(QtCore.Qt.AlignTop)
        self.setSpacing(10)
        
        self.menuLabel = QtGui.QLabel(node_type, parent)
        
        self.menu = QtGui.QListWidget(parent)
        
        # Read difference data if render node is
        # ifd (mantra) and has sampling parms
        if node_type != "ifd":
            self.menu.addItems(node_list)
        else:
            ifdItems = [n[0] for n in node_list]
            self.menu.addItems(ifdItems)
            
        self.menu.itemClicked.connect(self.selectNode)
        
        self.addWidget(self.menuLabel)
        self.addWidget(self.menu)
        
        self._OutFocusfilter = OutFocusFilter()
        self.menu.installEventFilter(self._OutFocusfilter)
        
    def selectNode(self):
        
        self.pickNodeUi.SELECTED_NODE = self.menu.currentItem().text()
        self.pickNodeUi.SELECTED_NODE_TYPE = self.menuLabel.text()
        

class OutFocusFilter(QtCore.QObject):
    '''
        Even Filter for loosing focus on menu.
    '''
    def eventFilter(self, widget, event):
        
        if event.type() == QtCore.QEvent.FocusOut:
            widget.reset()
            return False
        else:
            return False