from qgis.PyQt.QtCore import QAbstractTableModel, Qt, QVariant
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import (
    QAbstractSpinBox,
    QHeaderView,
    QLineEdit,
    QSpinBox,
    QStyledItemDelegate,
    QStyleOptionViewItem,
    QTableWidgetItem,
    QTreeWidgetItem,
)

from kfrm_tool.include.setting.path_list import DefaultPath


class SettingWidget:
    def __init__(self, treeWidget, loginType):
        self.pathList = DefaultPath()
        self.treeWidget = treeWidget
        self.loginType = loginType

        self.treeWidget.setItemDelegate(ItemDelegate())

    # TreeWidget 목록 세팅 이벤트
    def treeWidgetSetting(self):
        # 컬럼 리스트
        self.treeWidget.clear()

        firstColumn = ["Hazard", "Inventory", "Vulnerability", "Loss", "Report"]

        secondColumn = {
            firstColumn[0]: ["User Data", "Quick Flood mapping"],
            firstColumn[1]: [
                "Add Map",
                "Buildings",
                "Vehicles",
                "Population",
                "Agriculture",
                "User Defined Inventory",
            ],
            firstColumn[2]: [
                "Buildings",
                "Vehicles",
                "Population",
                "Agriculture",
                "User Defined Vulnerability",
            ],
            firstColumn[3]: [
                "Private Sector Loss",
                "Public Sector Loss",
                "Annualized Loss",
            ],
            firstColumn[4]: [],
        }

        thirdColumn = ["Valuation Parameters", "Evaluation & Summarize"]
        # 내용 삽입
        for f, first in enumerate(firstColumn):
            firstItem = QTreeWidgetItem([first])
            firstItem.setWhatsThis(0, "0")

            secondColumnList = secondColumn[first]
            for s, second in enumerate(secondColumnList):
                secondItem = QTreeWidgetItem([second])
                secondItem.setWhatsThis(0, "0")

                if f == 1 and s in [
                    1,
                    2,
                    4,
                ]:  # Inventory에서 Building, Vehicle, Agriculture만 세번째 하위 메뉴가 있음
                    for t, third in enumerate(thirdColumn):
                        thirdItem = QTreeWidgetItem([third])
                        thirdItem.setWhatsThis(0, "0")
                        secondItem.addChild(thirdItem)

                firstItem.addChild(secondItem)
                self.treeWidget.expandItem(secondItem)
            self.treeWidget.addTopLevelItem(firstItem)
            self.treeWidget.expandItem(firstItem)  # 항목 확장

        # stackedWidget index 설정을 위한 값
        self.treeWidget.topLevelItem(0).child(0).setWhatsThis(
            0, "1"
        )  # Hazard - User Data
        self.treeWidget.topLevelItem(0).child(1).setWhatsThis(
            0, "2"
        )  # Hazard - Level pool

        addMap = "3" if self.loginType else "4"
        self.treeWidget.topLevelItem(1).child(0).setWhatsThis(
            0, addMap
        )  # Inventory - Add Map
        self.treeWidget.topLevelItem(1).child(1).child(0).setWhatsThis(
            0, "5"
        )  # Inventory - Buildings - Valuation Parameters
        self.treeWidget.topLevelItem(1).child(1).child(1).setWhatsThis(
            0, "6"
        )  # Inventory - Buildings - Evaluation & Summarize
        self.treeWidget.topLevelItem(1).child(2).child(0).setWhatsThis(
            0, "7"
        )  # Inventory - Vehicle - Valuation Parameters
        self.treeWidget.topLevelItem(1).child(2).child(1).setWhatsThis(
            0, "8"
        )  # Inventory - Vehicle - Evaluation & Summarize
        self.treeWidget.topLevelItem(1).child(3).setWhatsThis(
            0, "9"
        )  # Inventory - Population
        self.treeWidget.topLevelItem(1).child(4).child(0).setWhatsThis(
            0, "10"
        )  # Inventory - Agriculture - Valuation Parameters
        self.treeWidget.topLevelItem(1).child(4).child(1).setWhatsThis(
            0, "11"
        )  # Inventory - Agriculture - Evaluation & Summarize

        self.treeWidget.topLevelItem(2).child(0).setWhatsThis(
            0, "12"
        )  # Vulnerability - Buildings
        self.treeWidget.topLevelItem(2).child(1).setWhatsThis(
            0, "13"
        )  # Vulnerability - Vehicle
        self.treeWidget.topLevelItem(2).child(2).setWhatsThis(
            0, "14"
        )  # Vulnerability - Population
        self.treeWidget.topLevelItem(2).child(3).setWhatsThis(
            0, "15"
        )  # Vulnerability - Agriculture

        self.treeWidget.topLevelItem(3).child(0).setWhatsThis(
            0, "16"
        )  # Loss - Private Sector Loss
        self.treeWidget.topLevelItem(3).child(1).setWhatsThis(
            0, "17"
        )  # Loss - Public Sector Loss
        self.treeWidget.topLevelItem(3).child(2).setWhatsThis(
            0, "18"
        )  # Loss - Annualized Loss

        # Disable
        self.treeWidget.topLevelItem(0).child(1).setFlags(Qt.NoItemFlags)
        self.treeWidget.topLevelItem(1).child(5).setFlags(Qt.NoItemFlags)
        self.treeWidget.topLevelItem(2).child(4).setFlags(Qt.NoItemFlags)
        self.treeWidget.topLevelItem(3).child(2).setFlags(Qt.NoItemFlags)
        self.treeWidget.topLevelItem(4).setFlags(Qt.NoItemFlags)

    def setCurrentCheckIcon(self):
        path = self.pathList.getCheckIconPath()
        icon = QIcon(path)
        self.treeWidget.currentItem().setIcon(0, icon)

    def setTreeItemSetIcon(self, item, path=None):
        if path is None:
            path = self.pathList.getCheckIconPath()
        icon = QIcon(path)
        item.setIcon(0, icon)

    def setTreeIconReset(self):
        topCount = self.treeWidget.topLevelItemCount()
        for i in range(topCount):
            topItem = self.treeWidget.topLevelItem(i)
            topItem.setIcon(0, QIcon(""))
            childCount = topItem.childCount()

            for j in range(childCount):
                childItem = topItem.child(j)
                childItem.setIcon(0, QIcon(""))
                thirdCount = childItem.childCount()

                for k in range(thirdCount):
                    thirdItem = childItem.child(k)
                    thirdItem.setIcon(0, QIcon(""))

    # TableWidget 기본 세팅
    def tableWidgetInit(
        self, table, header=[], contents=[], headerFlag=False, verticalFixed=True
    ):
        table.verticalHeader().setDefaultAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        if verticalFixed:
            table.verticalHeader().setDefaultSectionSize(20)  # ResizeToContents

        if header or headerFlag:
            headerLen = len(header)
            table.setColumnCount(headerLen)
            table.setHorizontalHeaderLabels(header)

        table.setRowCount(len(contents))

    def clearNSetTable(self, tbl, cnt):
        colCnt = tbl.columnCount()
        headers = []
        for i in range(colCnt):
            headers.append(tbl.horizontalHeaderItem(i).text())
        tbl.clear()
        tbl.setHorizontalHeaderLabels(headers)
        tbl.setRowCount(cnt)

    # TableWidget 내용 세팅
    def tableWidgetContentsSetting(
        self,
        table,
        contents,
        comma=[-1, -1],
        headerList=[],
        headerFlag=False,
        verticalFixed=True,
        decimal=4,
    ):
        self.tableWidgetInit(table, headerList, contents, headerFlag, verticalFixed)
        for j, row in enumerate(contents):
            for i, col in enumerate(row):
                align = Qt.AlignLeft | Qt.AlignVCenter
                col = str(col).strip() if col is not None else ""

                if i >= comma[0] and i < comma[1] and col != "":
                    align = Qt.AlignRight | Qt.AlignVCenter
                    col = self.stringFormats(col, decimal)

                widgetItem = QTableWidgetItem(col)
                widgetItem.setFlags(Qt.ItemIsEnabled)
                widgetItem.setTextAlignment(align)
                table.setItem(j, i, widgetItem)

    def tableViewContentsSetting(self, table, contents, headerList=[]):
        table.setSortingEnabled(False)
        model = TableModel(contents, headerList, table)
        table.setModel(model)
        table.verticalHeader().setDefaultAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        table.verticalHeader().setDefaultSectionSize(20)  # ResizeToContents

        decDelegate = TableItemDelegate(table)
        table.setItemDelegate(decDelegate)

    def tableWidgetAddWidgetSetting(
        self, table, contents, comma=[-1, -1], header=[], vertical=True, decimal=4
    ):
        self.tableWidgetInit(table, header, contents, verticalFixed=vertical)
        #         i = 0
        for row, filePath in enumerate(contents):
            widgetItem = QTableWidgetItem(filePath)
            widgetItem.setFlags(Qt.ItemIsEnabled)
            table.setItem(row, 0, widgetItem)

            spin = self.spinWidget(10000)
            table.setCellWidget(row, 1, spin)
            table.setCellWidget(row, 2, QLineEdit())

    #             table.setCellWidget(row, 1+i, spin)
    #             table.setCellWidget(row, 2+i, QLineEdit())

    def tableChageWidgetItemToSpin(self, table, col):
        row = table.rowCount()
        for r in range(row):
            val = int(table.item(r, col).text())
            spin = self.spinWidget(10000)
            spin.setValue(val)
            table.setCellWidget(r, col, spin)

    # TableWidget 한 줄 세팅
    def tableWidgetOneRowUpdate(self, table, row, col, first=0, last=1):
        for i in range(first, last):
            widgetItem = QTableWidgetItem(str(col))
            widgetItem.setTextAlignment(4 | 128)  # col center, row center
            widgetItem.setFlags(Qt.ItemIsEnabled)
            table.setItem(row, i, widgetItem)

    def tableWidgetOneLineUpdate(self, table, row, cols, first=0):
        for i, col in enumerate(cols):
            widgetItem = QTableWidgetItem(str(col))
            widgetItem.setTextAlignment(4 | 128)  # col center, row center
            widgetItem.setFlags(Qt.ItemIsEnabled)
            table.setItem(row, i + first, widgetItem)

    def tableWidgetOneColumnUpdate(self, table, data, col):
        for r, d in enumerate(data):
            widgetItem = QTableWidgetItem(str(d))
            #             widgetItem.setTextAlignment(4|128)  #col center, row center
            widgetItem.setFlags(Qt.ItemIsEnabled)
            table.setItem(r, col, widgetItem)

    def tableWidgetColumnEditable(
        self, table, first, last, oriContents, editFlag=True, decimal=4
    ):
        row = table.rowCount()
        for i in range(row):
            for j in range(first, last):
                if editFlag:
                    content = oriContents[i][j]
                    widgetItem = QTableWidgetItem(str(content))
                else:
                    content = self.stringFormats(table.item(i, j).text(), decimal)
                    widgetItem = QTableWidgetItem(str(content))
                    widgetItem.setFlags(Qt.ItemIsEnabled)

                widgetItem.setTextAlignment(2 | 128)
                table.setItem(i, j, widgetItem)

    def tableWidgetChangeNoneToZero(self, table, first, last):
        row = table.rowCount()
        for i in range(row):
            for j in range(first, last):
                items = table.item(i, j)
                if not items or not items.text():
                    table.setItem(i, j, QTableWidgetItem("0"))

    def tableHeaderStretch(self, table):
        colCount = table.columnCount()
        header = table.horizontalHeader()
        for i in range(colCount):
            header.setSectionResizeMode(i, QHeaderView.ResizeToContents)
            colWidth = table.columnWidth(i)
            header.setSectionResizeMode(i, QHeaderView.Interactive)
            table.setColumnWidth(i, colWidth)

    def stringFormats(self, content, decimalPoint):  # table widget 용도
        content = content.replace(",", "")
        try:
            if content.isdigit():  # int
                content = "{:,}".format(int(content))
            else:  # float
                content = "{0:,.{1}f}".format(float(content), decimalPoint)
        except ValueError as v:
            content = "0"

        return content

    def comboBoxInit(self, cmb, items=[]):
        cmb.clear()
        cmb.addItems(["- Select Value -"] + items)

    def spinWidget(self, vMax, vMin=0):
        spin = QSpinBox()
        spin.setMinimum(vMin)
        spin.setMaximum(vMax)
        spin.setButtonSymbols(QAbstractSpinBox.NoButtons)
        spin.wheelEvent = lambda event: None
        return spin


# QTableView Data setting 관련 class
class TableModel(QAbstractTableModel):
    def __init__(self, data, header, parent=None):
        super(TableModel, self).__init__(parent)
        self._data = data
        self.header_labels = header

    def rowCount(self, parent=None):
        return len(self._data)

    def columnCount(self, parent=None):
        return len(self._data[0]) if self.rowCount() else 0

    def data(self, index, role=Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return QVariant()
        return self._data[index.row()][index.column()]

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:
            return self.header_labels[section]
        return QAbstractTableModel.headerData(self, section, orientation, role)


class TableItemDelegate(QStyledItemDelegate):  # table View에 적용됨.
    def __init__(self, parent=None):
        super(TableItemDelegate, self).__init__(parent)
        self.parent = parent  # instance of the parent (not the base) class

    def displayText(self, data, locale):
        if type(data) == float:
            data = ("{0:,.{1}f}".format(data, 4)).strip()
        else:
            data = ("{0:>{1}}".format(data, 4)).strip()
        return data


class ItemDelegate(QStyledItemDelegate):
    def paint(self, painter, option, index):
        option.decorationPosition = QStyleOptionViewItem.Right
        super(ItemDelegate, self).paint(painter, option, index)
