import decimal

from qgis.core import (
    QgsDataSourceUri,
    QgsRuleBasedRenderer,
    QgsSimpleFillSymbolLayer,
    QgsSingleSymbolRenderer,
    QgsSymbol,
    QgsVectorLayer,
)
from qgis.PyQt.QtGui import QColor
from qgis.PyQt.QtWidgets import QTreeWidgetItem

from kfrm_tool.include.db.dao.pg_query_dao import PgQuery
from kfrm_tool.include.db.dao.sqlite_query_dao import SqliteQuery
from kfrm_tool.include.db.db_connection import PostgreSQLConnection
from kfrm_tool.include.setting.path_list import DefaultPath

# from ..db.dao.sqlite_query_dao import SqliteQuery


class LayerTools:
    def __init__(self, sqliteQuery: SqliteQuery):
        self.pg = PostgreSQLConnection()
        self.pgQuery = PgQuery()
        self.sqlQuery = sqliteQuery
        self.path = DefaultPath()

    # DB에 있는 Table 값을 가져와 QGIS에 적용할 수 있도록 레이어로 변경
    def convertTableToLayer(
        self, dbType, tableName, sql="", layerName="", pk="ogc_fid"
    ):
        SCHEMA = ""
        DB_KIND = dbType
        uri = QgsDataSourceUri()

        if dbType == "postgres":
            geoName = self.pgQuery.getGeometryInfo(tableName)
            GEOMETRY = geoName[0][3] if geoName else ""
            HOST = self.pg.getHost()
            PORT = self.pg.getPort()
            DB_NAME = self.pg.getDbName()
            USER_ID = self.pg.getUserName()
            PASSWORD = self.pg.getPassword()
            uri.setConnection(HOST, PORT, DB_NAME, USER_ID, PASSWORD)
            uri.setDataSource(SCHEMA, sql, GEOMETRY, "", pk)  # Sql 쿼리 문으로 필요한 구역만 가져옴.

        elif dbType == "spatialite":
            geoName = self.sqlQuery.getGeometryInfo(tableName)
            GEOMETRY = geoName[1] if geoName else ""
            dbPath = self.path.getSqliteDBPath()
            uri.setDatabase(dbPath)
            uri.setDataSource(SCHEMA, tableName, GEOMETRY)

        layerName = layerName if layerName else tableName
        layer = QgsVectorLayer(uri.uri(), layerName, DB_KIND)

        return layer

    # 단일 색, 선 두께, 선 색 변경
    def setSymbolStyle(self, layer, color, widthBorder="0.26", borderColor="0, 0, 0"):
        symbol = QgsSymbol.defaultSymbol(layer.geometryType())
        renderer = QgsSingleSymbolRenderer(symbol)

        layer_style = {}
        layer_style["color"] = color
        layer_style["width_border"] = widthBorder
        layer_style["color_border"] = borderColor
        symbol_layer = QgsSimpleFillSymbolLayer.create(layer_style)

        renderer.symbol().changeSymbolLayer(0, symbol_layer)
        layer.setRenderer(renderer)  # 랜더링 변경
        layer.triggerRepaint()

    # 한 컬럼의 값에 따라 색 차등 배열
    def setSymbolRule(self, vlayer, name, min=0.3, max=3.0):
        try:
            # 룰 적용 : 룰 이름, 적용 식, 적용 색, 키 값
            value = []
            for i in range(0, 10):
                n = round(decimal.Decimal(min * i), 1)
                m = round(decimal.Decimal(min * (i + 1)), 1)
                value.append(
                    tuple(
                        [
                            f"{i+1} ({n}~{m})",  # 표시되는 이름
                            f'"{name}"={i+1}',  # 적용되는 룰 값
                            # f'"{name}">={i} AND "{name}"<{i+1}', #적용되는 룰 값
                            QColor(255 - 23 * i, 255 - 22 * i, 255 - 3 * i),  # R, G, B
                            None,
                        ]
                    )
                )
            value.append(
                tuple([f"11 ({max}~)", f'"{name}"=11', QColor(0, 0, 255), None])
            )
            road_rules = tuple(value)

            # layer의 기본 룰 불러오기
            symbol = QgsSymbol.defaultSymbol(vlayer.geometryType())
            renderer = QgsRuleBasedRenderer(symbol)
            root_rule = renderer.rootRule()

            for label, expression, color_name, scale in road_rules:
                rule = root_rule.children()[0].clone()  # rule의 기본값을 바탕으로 클론 생성

                rule.setLabel(label)  # 텍스트 지정
                rule.setFilterExpression(expression)  # 식 지정
                rule.symbol().setColor(QColor(color_name))  # 색 지정

                # set the scale limits if they have been specified
                if scale is not None:
                    rule.setScaleMinDenom(scale[0])
                    rule.setScaleMaxDenom(scale[1])

                root_rule.appendChild(rule)  # 룰 추가
            root_rule.removeChildAt(0)

            vlayer.setRenderer(renderer)  # 랜더링 변경
            vlayer.triggerRepaint()  # 레이어 다시 그리기

        except Exception as e:
            raise Warning(e)

    # 심볼의 모양을 네모 모양이 아닌, 폴리곤 형태로 표현하기 위한 함수
    def setSingleSymbolRule(self, vlayer):
        try:
            oriRenderer = vlayer.renderer()
            if oriRenderer != QgsSingleSymbolRenderer and vlayer.geometryType() != 2:
                # 단일 심볼이 아니거나, Polygon이 아닌 경우에는 pass
                return

            color = oriRenderer.legendSymbolItems()[-1].symbol().color()
            symbol = QgsSymbol.defaultSymbol(vlayer.geometryType())
            renderer = QgsRuleBasedRenderer(symbol)
            root_rule = renderer.rootRule()

            rule = root_rule.children()[0].clone()
            rule.setLabel(" ")
            rule.setFilterExpression("")
            rule.symbol().setColor(color)

            root_rule.appendChild(rule)
            root_rule.removeChildAt(0)

            vlayer.setRenderer(renderer)
            vlayer.triggerRepaint()

        except Exception as e:
            raise Warning(str(e))

    # TreeWidget에 룰 이름(적용 값 범위) 표시
    def layerLegend(self, tree, road_rules):
        try:
            tree.clear()
            for label, expression, colors, scale in road_rules:
                item = QTreeWidgetItem(["  \u2588\u2588   ", label])
                item.setForeground(0, colors)
                tree.addTopLevelItem(item)

            tree.resizeColumnToContents(0)

        except Exception as e:
            raise Warning(e)
