import os
import re
from datetime import datetime

from PyQt5.QtCore import QVariant, QThread, pyqtSignal
from qgis.PyQt import uic, QtWidgets, QtCore
from qgis._core import QgsFeatureRequest, QgsMapLayer, QgsWkbTypes, QgsCoordinateReferenceSystem, \
    QgsCoordinateTransform, QgsProject, QgsGeometry, QgsGeometryCollection, QgsVectorLayer, QgsFields, QgsField, \
    QgsFeature, Qgis, QgsPointXY
from qgis.utils import iface


FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'cyanlove_buffer_base.ui'))


class cyanlove_buffer(QtWidgets.QDockWidget, FORM_CLASS):
    closingPlugin = pyqtSignal()

    def __init__(self, parent=None):
        super(cyanlove_buffer, self).__init__(parent)

        self.export_thread = None
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.setupUi(self)
        self.setFloating(True)
        self.property_dict = None  # 存储搜索出来的名称，图元中心经纬度
        self.is_running = False  # 线程状态标志
        self.setWindowFlags(QtCore.Qt.Dialog)  # 使对话框始终在前
        # 设置为模态窗口
        # self.setWindowModality(QtCore.Qt.ApplicationModal)  # 或者使用 Qt.WindowModal
        self.mFieldComboBox.setLayer(self.mMapLayerComboBox.currentLayer())
        self.btn_value_buffer.clicked.connect(self.on_btn_value_buffer)
        self.btn_column_buffer.clicked.connect(self.on_btn_column_buffer)
        self.mMapLayerComboBox.currentIndexChanged.connect(self.selectindexchange)
        self.textEdit_value_buffer.setText('300')

    def selectindexchange(self):
        self.mFieldComboBox.setLayer(self.mMapLayerComboBox.currentLayer())

    def update_label(self, value):
        self.label_show.setText(value)  # 更新值

    def on_btn_value_buffer(self):

        current_layer = self.mMapLayerComboBox.currentLayer()
        if current_layer is None or current_layer.type() != QgsMapLayer.VectorLayer:
            self.label_show.setText("选择的图层不是矢量图层！")
            return

        # 缓冲的距离
        buffer_value = 300
        buffer_valueset = self.textEdit_value_buffer.toPlainText()

        if re.match(r'^[1-9]\d*$', buffer_valueset):
            buffer_value = int(buffer_valueset)
        else:
            self.label_show.setText("输入无效，必须是一个正整数。")
            return
        self.label_show.setText("缓冲开始...")
        # 创建一个图层
        timestamp = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
        layname = 'SSJ_buffer_' + timestamp
        layers = QgsProject.instance().mapLayersByName(layname)
        if layers:
            for layer in layers:
                QgsProject.instance().removeMapLayer(layer.id())

        layer = QgsVectorLayer("Polygon?crs=EPSG:4326", layname, "memory")

        provider = layer.dataProvider()  # 获取图层的数据提供者
        fields = QgsFields()  # 创建字段集合
        # 添加属性字段到字段集合
        for field in current_layer.fields():
            fields.append(QgsField(field.name(), field.type()))  # 复制字段名称和类型
        # 将字段添加到数据提供者
        provider.addAttributes(fields)
        layer.updateFields()  # 更新图层的字段
        self.progressBar.setRange(0, 100)  # 设置进度条范围
        self.progressBar.setValue(0)  # 初始化进度条值
        self.export_thread = ExportThread(current_layer, provider, buffer_value, None)
        self.export_thread.updatelabel.connect(self.update_label)
        self.export_thread.progress.connect(self.update_progress)  # 连接信号到槽
        self.export_thread.layerAdded.connect(lambda: QgsProject.instance().addMapLayer(layer, True))
        self.export_thread.finished.connect(self.on_thread_finished)  # 连接线程结束信号
        self.export_thread.start()

    def on_btn_column_buffer(self):
        print("start..buffer...")
        current_layer = self.mMapLayerComboBox.currentLayer()
        if current_layer is None or current_layer.type() != QgsMapLayer.VectorLayer:
            self.label_show.setText("选择的图层不是矢量图层！")
            return

        self.label_show.setText("缓冲开始...")
        # 创建一个图层
        timestamp = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
        layname = 'SSJ_buffer_' + timestamp
        layers = QgsProject.instance().mapLayersByName(layname)
        if layers:
            for layer in layers:
                QgsProject.instance().removeMapLayer(layer.id())

        layer = QgsVectorLayer("Polygon?crs=EPSG:4326", layname, "memory")

        provider = layer.dataProvider()  # 获取图层的数据提供者
        fields = QgsFields()  # 创建字段集合
        # 添加属性字段到字段集合
        for field in current_layer.fields():
            fields.append(QgsField(field.name(), field.type()))  # 复制字段名称和类型
        # 将字段添加到数据提供者
        provider.addAttributes(fields)
        layer.updateFields()  # 更新图层的字段
        selectcolname = self.mFieldComboBox.currentField()  # 当前选择的字段
        self.progressBar.setRange(0, 100)  # 设置进度条范围
        self.progressBar.setValue(0)  # 初始化进度条值
        self.export_thread = ExportThread(current_layer, provider, None, selectcolname)
        self.export_thread.updatelabel.connect(self.update_label)
        self.export_thread.progress.connect(self.update_progress)  # 连接信号到槽
        self.export_thread.layerAdded.connect(lambda: QgsProject.instance().addMapLayer(layer, True))
        self.export_thread.finished.connect(self.on_thread_finished)  # 连接线程结束信号
        self.export_thread.start()

    def on_thread_finished(self):
        self.iface.mapCanvas().refresh()
        print("缓冲完成！")
        self.label_show.setText("缓冲完成！")
        self.progressBar.setValue(100)

    def update_progress(self, value):
        self.progressBar.setValue(value)  # 更新进度条的值


class ExportThread(QThread):
    progress = pyqtSignal(int)  # 声明一个进度信号
    layerAdded = pyqtSignal()  # 声明一个图层新增信号
    updatelabel = pyqtSignal(str)  # 声明一个更新label新增信号

    def __init__(self, layerselect, provider, buffer_value=None, buffer_colname=None):
        super().__init__()  # 初始化父类
        self.layerselect = layerselect
        self.buffer_value = buffer_value
        self.provider = provider
        self.buffer_colname = buffer_colname

    def run(self):

        # 要素的总数
        total_features = self.layerselect.featureCount()
        feature_list = self.layerselect.getFeatures()
        geom_type = self.layerselect.wkbType()

        # 如果是点图层，则调用点的缓冲
        if geom_type in [QgsWkbTypes.Point, QgsWkbTypes.MultiPoint,
                         QgsWkbTypes.Polygon, QgsWkbTypes.MultiPolygon,
                         QgsWkbTypes.LineString, QgsWkbTypes.MultiLineString]:
            if self.buffer_value is not None:
                self.mmqgis_buffer_geometry_value(feature_list, total_features)
            if self.buffer_colname is not None:
                print(self.buffer_colname)
                self.mmqgis_buffer_geometry_colname(feature_list, total_features)
        else:
            self.updatelabel.emit(f"错误: 不是预想的图层！")
        # 发出图层新增信号
        self.layerAdded.emit()

    def mmqgis_buffer_geometry_value(self, feature_list, total_features):
        # 循环
        for feature_index, feature in enumerate(feature_list):
            progress_value = int((feature_index + 1) / total_features * 100)  # 计算进度百分比
            self.progress.emit(progress_value)  # 发出进度信号

            try:
                geometry = feature.geometry()
                wgs84 = QgsCoordinateReferenceSystem("EPSG:4326")

                # 高斯吕格投影
                gslg_crs = QgsCoordinateReferenceSystem("EPSG:32648")
                transform_equ = QgsCoordinateTransform(wgs84, gslg_crs, QgsProject.instance())
                geometry.transform(transform_equ)

                newgeometry = geometry.buffer(self.buffer_value, 32)

                wgs84 = QgsCoordinateReferenceSystem()
                wgs84.createFromProj4("+proj=longlat +datum=WGS84 +no_defs")

                transform_wgs84 = QgsCoordinateTransform(gslg_crs, wgs84, QgsProject.instance())
                newgeometry.transform(transform_wgs84)

                if newgeometry:
                    new_feature = QgsFeature(feature)  # 复制原特征
                    new_feature.setGeometry(newgeometry)  # 设置缓冲几何对象
                    self.provider.addFeatures([new_feature])  # 将特征添加到数据提供者
                # 计算并发出进度信号

            except Exception as e:
                pass

    def mmqgis_buffer_geometry_colname(self, feature_list, total_features):
        # 循环

        for feature_index, feature in enumerate(feature_list):
            progress_value = int((feature_index + 1) / total_features * 100)  # 计算进度百分比
            self.progress.emit(progress_value)  # 发出进度信号
            try:

                buffer_col = feature[self.buffer_colname]
                try:
                    buffer_valueset = int(float(buffer_col))  # Convert to float first, then int
                    if buffer_valueset <= 0:
                        buffer_valueset = 1
                except (ValueError, TypeError):
                    buffer_valueset = 1


                geometry = feature.geometry()
                wgs84 = QgsCoordinateReferenceSystem("EPSG:4326")

                # 高斯吕格投影
                gslg_crs = QgsCoordinateReferenceSystem("EPSG:32648")
                transform_equ = QgsCoordinateTransform(wgs84, gslg_crs, QgsProject.instance())
                geometry.transform(transform_equ)

                newgeometry = geometry.buffer(buffer_valueset, 32)

                wgs84 = QgsCoordinateReferenceSystem()
                wgs84.createFromProj4("+proj=longlat +datum=WGS84 +no_defs")

                transform_wgs84 = QgsCoordinateTransform(gslg_crs, wgs84, QgsProject.instance())
                newgeometry.transform(transform_wgs84)

                if newgeometry:
                    new_feature = QgsFeature(feature)  # 复制原特征
                    new_feature.setGeometry(newgeometry)  # 设置缓冲几何对象
                    self.provider.addFeatures([new_feature])  # 将特征添加到数据提供者
                # 计算并发出进度信号

            except Exception as e:

                print(f"{feature_index} {str(e)}")
