import csv
import hashlib
import json
import math
import os
import time
import urllib



import requests
from PyQt5.QtCore import QVariant, QThread, pyqtSignal, Qt
from qgis.PyQt import uic

from qgis._core import QgsFillSymbol, QgsMarkerSymbol, QgsVectorLayer, QgsLayerTreeLayer, QgsProject, QgsFields, \
    QgsField, QgsGeometry, QgsPointXY, QgsFeature, QgsSingleSymbolRenderer
from qgis.utils import iface
from PyQt5 import QtCore, QtWidgets

from .cyanlove_config_read_intfile import readconfig
from .cyanlove_transform_gps_to_gps import Mecator_to_gps

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


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

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

        self.export_thread = None
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.setupUi(self)
        self.setFloating(True)
        self.layer = None
        self.setWindowFlags(QtCore.Qt.Dialog)  # 使对话框始终在前
        # 设置为模态窗口
        # self.setWindowModality(QtCore.Qt.ApplicationModal)  # 或者使用 Qt.WindowModal
        self.toolButton.clicked.connect(self.draw_aoi)
        self.plainTextEdit.setTabChangesFocus(True)

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

    # 重写

    def draw_aoi(self):
        city = self.plainTextEdit.toPlainText().strip()
        searchstr = self.plainTextEdit_aoi.toPlainText().strip()
        if city is None or searchstr is None:
            self.label_show.setText("填写不正确！")
            return
        else:
            aky = readconfig.read_ini_file('Settings', 'baidu_key')
            if aky == "":
                self.label_show.setText("没有配置百度Key")
                return
            layName = "SSJ_AOI"
            layerlist = QgsProject.instance().mapLayersByName(layName)
            if layerlist:
                print('cunzai')
                self.layer = layerlist[0]  # 获取列表中的第一个图层
                fields = self.layer.fields()
                provider = self.layer.dataProvider()  # 获取图层的数据提供者
                self.export_thread = ExportThread(provider, fields, city, searchstr, aky)
                self.export_thread.updatelabel.connect(self.update_label)
                self.export_thread.pan_to_featureid.connect(self.pan_to_featureid)
                self.export_thread.start()  # 启动线程
            else:
                self.layer = QgsVectorLayer("Polygon?crs=EPSG:4326", layName, "memory")
                provider = self.layer.dataProvider()  # 获取图层的数据提供者
                fields = QgsFields()  # 创建字段集合
                fields.append(QgsField("name", QVariant.String))  # 添加字符串类型字段
                provider.addAttributes(fields)  # 将字段添加到数据提供者
                self.layer.updateFields()  # 更新图层的字段
                fill_symbol = QgsFillSymbol.createSimple({'color': '241,248,44,128',
                                                          'outline_color': '255,0,35,255',
                                                          'outline_width': '0.5',
                                                          'style': 'solid'})  # alpha 值范围 0-255，0 完全透明，255 不透明
                renderer = QgsSingleSymbolRenderer(fill_symbol)
                self.layer.setRenderer(renderer)
                QgsProject.instance().addMapLayer(self.layer, True)
                # 开始线程
                self.export_thread = ExportThread(provider, fields, city, searchstr, aky)
                self.export_thread.updatelabel.connect(self.update_label)
                self.export_thread.pan_to_featureid.connect(self.pan_to_featureid)
                self.export_thread.start()  # 启动线程

    # 平移到位置
    def pan_to_featureid(self, feature_id_list):
        if self.layer:
            self.canvas.setCenter(feature_id_list)
            self.canvas.refresh()


class ExportThread(QThread):
    updatelabel = pyqtSignal(str)  # 声明一个更新label新增信号
    pan_to_featureid = pyqtSignal(QgsPointXY)

    def __init__(self, provider, fields, city, searchstr, aky):
        super().__init__()
        self.provider = provider
        self.fields = fields
        self.city = city
        self.searchstr = searchstr
        self.aky = aky

    def run(self):

        self.updatelabel.emit("查询中...")
        result = self.get_baidu_json(self.city, self.searchstr, self.aky)
        print(result['status'])
        if result['status'] == 0:
            panToFeatureIds = None
            counta = len(result['result'])
            k = 1
            for dt in result['result']:
                try:
                    # 查询的结果
                    time.sleep(0.2)
                    self.updatelabel.emit(f"Start: {k}/{counta}")
                    k = k + 1
                    AOI_name, point_transformlist = self.getaoi(dt)
                    # 只提取有边界的AOI
                    if len(point_transformlist) > 0:
                        points = [QgsPointXY(x, y) for x, y in point_transformlist]
                        # 使用 fromPolygonXY 创建多边形几何对象
                        geom = QgsGeometry.fromPolygonXY([points])
                        if geom.isGeosValid():
                            feature = QgsFeature(self.fields)  # 创建新特征
                            feature["name"] = AOI_name
                            feature.setGeometry(geom)  # 设置几何对象
                            panToFeatureIds = points[0]
                            self.provider.addFeatures([feature])  # 将特征添加到数据提供者
                        else:
                            print("error,不是边界")

                except Exception as e:
                    print(f"  {str(e)}")
                    self.updatelabel.emit(f"其余：{str(e)})")

            # 平移
            if panToFeatureIds:
                self.pan_to_featureid.emit(panToFeatureIds)

            self.updatelabel.emit("查询完毕！")
        else:
            error_dict = {
                "1": "服务器内部错误",
                "2": "请求参数非法",
                "3": "权限校验失败",
                "4": "配额校验失败",
                "5": "ak不存在或者非法",
                "8": "数据解析失败",
                "9": "高级权限校验失败",
                "101": "AK参数不存在",
                "200": "APP不存在，AK有误请检查再重试",
                "201": "APP被用户自己禁用，请在控制台解禁",
                "202": "APP被管理员删除",
                "203": "APP类型错误",
                "210": "APP IP校验失败",
                "211": "APP SN校验失败",
                "240": "APP 服务被禁用",
                "250": "用户不存在",
                "251": "用户被自己删除",
                "252": "用户被管理员删除",
                "260": "服务不存在",
                "261": "服务被禁用",
                "302": "天配额超限，限制访问",
                "401": "当前并发量已经超过约定并发配额，限制访问"
            }
            if str(result['status']) in error_dict:
                print("S:" + str(result['status']))  # 确保你打印的是字符串
                self.updatelabel.emit(f"错误：{error_dict[str(result['status'])]}")
            else:
                self.updatelabel.emit("错误：出现异常，无法识别的状态")

    @staticmethod
    def get_baidu_json(city, searchstr, aky):
        baiduurl = "https://api.map.baidu.com"
        # 有额度限制
        queryStr = ("/place/v2/suggestion?query=" + searchstr + "&region=" + city +
                    "&city_limit=true&coord_type=1&output=json&ak=" + aky)

        encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
        sign = hashlib.md5(urllib.parse.quote_plus(encodedStr).encode("utf8")).hexdigest()
        # 拼接
        qqurl = baiduurl + queryStr + '&sn=' + sign
        data = requests.request('GET', qqurl, timeout=5).content.decode('utf-8')
        dataa = json.loads(data)

        return dataa

    @staticmethod
    def getaoi(dts):
        point_transform = []
        AOI_name = None
        if 'location' in dts:
            try:
                AOI_id = dts['uid']
                AOI_name = dts['name']
                uel_AOI = 'https://map.baidu.com/?newmap=1&qt=ext&uid=' + AOI_id + '&ext_ver=new&ie=utf-8&l=11'
                r_AOI = requests.request('GET', uel_AOI, timeout=5).content.decode('utf-8')
                data_AOI = json.loads(r_AOI)
                xy = dts['location']
                nxy = Mecator_to_gps.BD092WGS84([float(xy['lng']), float(xy['lat'])])
                dts['location'] = nxy
                if 'geo' in data_AOI['content']:
                    print('有aoi')
                    geo_AOI = data_AOI['content']['geo']
                    geo_AOI = geo_AOI.split('|')
                    point = geo_AOI[2].split(",")
                    for i in range(int(len(point) / 2)):  # 全部点的坐标，分别是x,y,的形式
                        if i == 0:  # 第一个点的x坐标删除‘1-’
                            point[2 * i] = point[2 * i][2:]
                        if i == int((len(point) / 2) - 1):  # 最后的点的y坐标删除‘;’
                            point[2 * i + 1] = point[2 * i + 1][:-1]
                        point_Mecator2BD09 = Mecator_to_gps.Mecator2BD09(float(point[2 * i]), float(point[2 * i + 1]))
                        point_BD092WGS84 = Mecator_to_gps.BD092WGS84(point_Mecator2BD09)
                        point_transform.append(point_BD092WGS84)

            except requests.exceptions.Timeout:
                print("请求超时")
            except requests.exceptions.RequestException as e:
                print(f"请求发生错误: {e}")

        return [AOI_name, point_transform]
