#  -------------------------------------------------------------------------
#  pyCGNS - Python package for CFD General Notation System - 
#  See license.txt file in the root directory of this Python module source  
#  -------------------------------------------------------------------------
#
from __future__ import unicode_literals
from builtins import (str, bytes, range, dict)


import os

from qtpy.QtCore import Qt
from qtpy.QtGui import QFont
from qtpy.QtWidgets import QTreeView, QFileDialog, QTreeWidgetItem, QWidget


import CGNS.NAV.wmessages as MSG
import CGNS.VAL.parse.messages as CGM
from CGNS.NAV.Q7DiagWindow import Ui_Q7DiagWindow
from CGNS.NAV.moption import Q7OptionContext as OCTXT
from CGNS.NAV.wfingerprint import Q7Window as QW
from CGNS.VAL.parse.findgrammar import locateGrammars


# -----------------------------------------------------------------
class Q7CheckList(QW, Ui_Q7DiagWindow):
    def __init__(self, parent, data, fgindex):
        QW.__init__(self, QW.VIEW_DIAG, parent._control, None, fgindex)
        self._currentItem = 0
        self._filterItems = {}
        self.bClose.clicked.connect(self.reject)
        self.bExpandAll.clicked.connect(self.expand)
        self.bInfo.clicked.connect(self.infoDiagView)
        self.bCollapseAll.clicked.connect(self.collapse)
        self.bPrevious.clicked.connect(self.previousfiltered)
        self.bNext.clicked.connect(self.nextfiltered)
        self.cWarnings.clicked.connect(self.reset)
        self.cDiagFirst.clicked.connect(self.reset)
        self.bSave.clicked.connect(self.diagnosticssave)
        self.bWhich.clicked.connect(self.grammars)
        self.cFilter.currentIndexChanged[int].connect(self.filterChange)
        # QObject.connect(self.cFilter,
        #                 SIGNAL("currentIndexChanged(int)"),
        #                 self.filterChange)
        self._data = data
        self._parent = parent
        self.diagTable.keyPressEvent = self.diagTableKeyPressEvent
        self.filterChange()

    def doRelease(self):
        pass

    def grammars(self):
        self.FG.pushGrammarPaths()
        gl = ""
        for g in locateGrammars():
            gl += "%s : %s<br>" % (g[0], os.path.split(g[1])[0])
        self.FG.popGrammarPaths()
        MSG.wInfo(self, 400, "Diag view:",
                  """Checks performed using the following grammars:<br>%s""" % gl,
                  again=False)

    def diagTableKeyPressEvent(self, event):
        kmod = event.modifiers()
        kval = event.key()
        if kval == Qt.Key_Space:
            itlist = self.diagTable.selectedItems()
            it = itlist[0]
            itxt = it.text(0)
            if itxt[0] != '/':
                itxt = it.parent().text(0)
            self._parent.treeview.selectByPath(itxt)
        else:
            QTreeView.keyPressEvent(self.diagTable, event)

    def infoDiagView(self):
        self._control.helpWindow('Diagnosis')

    def diagnosticssave(self):
        n = 'data=%s\n' % self._data

        filename = QFileDialog.getSaveFileName(self,
                                               "Save diagnosis", ".", "*.py")
        if filename[0] == "":
            return
        with open(str(filename[0]), 'w+') as f:
            f.write(n)

    def previousfiltered(self):
        iold = self._filterItems[self.cFilter.currentText()][self._currentItem]
        if self._currentItem != 0:
            self._currentItem -= 1
        inew = self._filterItems[self.cFilter.currentText()][self._currentItem]
        iold.setSelected(False)
        inew.setSelected(True)
        self.diagTable.scrollToItem(inew)
        self.eCount.setText(str(self._currentItem + 1))

    def nextfiltered(self):
        ilist = self._filterItems[self.cFilter.currentText()]
        if self._currentItem >= len(ilist) - 1:
            return
        iold = ilist[self._currentItem]
        self._currentItem += 1
        inew = ilist[self._currentItem]
        iold.setSelected(False)
        inew.setSelected(True)
        self.diagTable.scrollToItem(inew)
        self.eCount.setText(str(self._currentItem + 1))

    def filterChange(self):
        self._currentItem = 0
        self.eCount.setText("")
        self.diagTable.clearSelection()

    def expand(self):
        self.diagTable.expandAll()

    def collapse(self):
        self.diagTable.collapseAll()

    def show(self):
        self.reset()
        super(Q7CheckList, self).show()

    def reset(self):
        v = self.diagTable
        v.clear()
        v.setHeaderHidden(True)
        plist = list(self._data)
        plist.sort()
        plist.reverse()
        keyset = set()
        self.cFilter.clear()
        self._filterItems = {}
        diagfirst = self.cDiagFirst.isChecked()
        warnings = self.cWarnings.isChecked()        
        diagstack = {}
        for path in plist:
            path_item = None
            state = self._data.getWorstDiag(path)
            if (state in [CGM.CHECK_NONE, CGM.CHECK_PASS]):
                pass
            elif (state == CGM.CHECK_WARN) and not warnings:
                pass
            else:
                for (diag, pth) in self._data.diagnosticsByPath(path):
                    if (diag.level == CGM.CHECK_WARN) and not warnings:
                        pass
                    elif diagfirst:
                        if diag.key not in keyset:
                            keyset.add(diag.key)
                            diag_item = self.addDiagEntry(None, diag, top=True)
                            v.insertTopLevelItem(0, diag_item)
                            diagstack[diag.key] = diag_item
                        path_item = self.addPathEntry(diagstack[diag.key],
                                                      path,
                                                      state, top=False)
                    else:
                        if diag.key not in keyset:
                            keyset.add(diag.key)
                        if path_item is None:
                            path_item = self.addPathEntry(None, path,
                                                          state, top=True)
                            v.insertTopLevelItem(0, path_item)
                        diag_item = self.addDiagEntry(path_item, diag,
                                                      top=False)
                    keylist = list(keyset)
        keylist.sort()
        for k in keylist:
            self.cFilter.addItem(k)

    def addPathEntry(self, parent, path, state, top=False):
        it = QTreeWidgetItem(parent, (path,))
        ft = QFont(OCTXT._Table_Font)
        if top:
            ft.setBold(True)
        it.setFont(0, ft)
        if state == CGM.CHECK_FAIL:
            it.setIcon(0, self.IC(QW.I_C_SFL))
        if state == CGM.CHECK_WARN:
            it.setIcon(0, self.IC(QW.I_C_SWR))
        return it

    def addDiagEntry(self, parent, diag, top=False):
        dit = QTreeWidgetItem(parent, (self._data.message(diag),))
        ft = QFont(OCTXT._Table_Font)
        if top:
            ft.setBold(True)
        dit.setFont(0, ft)
        if diag.level == CGM.CHECK_FAIL:
            dit.setIcon(0, self.IC(QW.I_C_SFL))
        if diag.level == CGM.CHECK_WARN:
            dit.setIcon(0, self.IC(QW.I_C_SWR))
        if diag.key not in self._filterItems:
            self._filterItems[diag.key] = [dit]
        else:
            self._filterItems[diag.key].insert(0, dit)
        return dit
        
    def reject(self):
        self.close()

    def close(self):
        self._parent.diagview = None
        QWidget.close(self)

# -----------------------------------------------------------------
