import math
import os.path
import typing
from yangke.base import interpolate_value_complex, interpolate_2d
from yangke.ebsilon.graphicsview import YkGraphicsItem, Port, PipeItem
from yangke.ebsilon.constant.constant import Pressure, Temperature, Enthalpy, MassFlow, Power, Length, Area, One, Other, \
    VolumeFlow, SpecificVolume, AngleUnit, Velocity, Density
from yangke.ebsilon.values import Value
from yangke.performance.iapws97 import get_h_by_pt, IAPWS97, get_rho_by_pt, get_t_by_ph
from yangke.common.QtImporter import QRectF, QLineF, QPointF, Qt, QPoint, QPainter, QWidget, QStyleOptionGraphicsItem, \
    QIcon

SpecificationValues = {
    "流体状态参数(总，滞止)": [
        ["温度计算方式", "TTYPE", ['1:绝热', '2:外部指定', '3:内部指定'], None],
    ],
    "管道结构参数": [
        ["结构类型", "TYPE", ["弯管", "热压弯管", "锻造弯管", "焊接弯管"], None],
        ["公称直径", "DN", "", Length("m")],
        ["内径", "DI", "", Length("m")],
        ["计算类型", "CTYPE", ["1:R", "2:R/DN"], None],
        ["转弯半径", "R", "", Length("m"), "show if CTYPE='1:R' and TYPE!='弯头'"],
        ["转弯比", "R/DN", "", None, "show if CTYPE=='2:R/DN' and TYPE!='弯头'"],
        ["弯曲角度", "ANGLE", "", AngleUnit("°")],
    ],
    "管道材质": [
        ["材质", "MAT", ["冷拔钢管", "普通钢管/熟铁管", "涂沥青铸铁管", "镀锌铸铁管", "其他"], None],  # 材质决定等值粗糙度
        ["等值粗糙度", "EPSILON", "", Length("mm"), "func:等值粗糙度(MAT)"]  # 该参数的值由函数 等值粗糙度(MAT)决定。如果制定了材质，则该值不可编辑
    ],

}  # 不能有逗号

Result = {
    "Total": [
        ["雷诺数", "Re", "", One()],
        ["介质运动粘度", "Gamma", "", Other("m^2/s")],
        ["介质动力粘度", "mu", "", Other("Pa·s")],
        ["管道截面积", "A", "", Area("m^2"), "tacit"],
        ["质量流量", "M", "", MassFlow("t/h")],
        ["体积流量", "VM", "", VolumeFlow("m^3/h")],
        ["介质密度", "Density", "", Density("kg/m^3")],
        ["平均流速", "Velocity", "", Velocity("m/s")],
        ["阻力系数", "K", "", One()],

    ]
}


class Item(YkGraphicsItem):
    def __init__(self):
        """

        """
        super(Item, self).__init__()
        self.width = 80
        self.height = 20
        self.EBS_ID = 10002  # ebsilon软件中的组件id
        self.NAME = "弯头DLT 5054"
        self.EBS_NAME = None  # ebsilon中的组件名
        self.EBS_TYPE = None  # ebsilon帮助文件中组件所属的组
        self.icon = QIcon(os.path.join(os.path.dirname(__file__), "Comp13.PNG"))  # 组件的图标

        # Ebsilon组件面板中的Ports页信息
        self.ports = {
            1: Port(idx=1, point=QPointF(-40, 0), type1="Inlet", description="Inlet port"),
            2: Port(idx=2, point=QPointF(40, 0), type1="Outlet", description="Outlet port")
        }
        self.SpecificationValues = SpecificationValues
        self.Result = Result

    def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem,
              widget: typing.Optional[QWidget] = ...) -> None:
        """
        绘制组件图形

        :param painter:
        :param option:
        :param widget:
        :return:
        """
        # 绘制组件实体
        self.pen[0].setColor(Qt.red)
        self.pen[0].setWidth(4)
        painter.setPen(self.pen[0])
        painter.drawLine(QLineF(QPointF(-30, 0), QPointF(-40, 0)))
        painter.drawLine(QLineF(QPointF(30, 0), QPointF(40, 0)))

        self.pen[1].setColor(Qt.black)
        self.pen[1].setWidth(1)
        painter.setPen(self.pen[1])
        self.brush[1].setColor(Qt.yellow)
        painter.setBrush(self.brush[1])
        painter.drawPolygon([QPoint(-30, -10), QPoint(30, -10), QPoint(30, 10), QPoint(-30, 10)], Qt.OddEvenFill)  # 三角形

        super(Item, self).paint(painter, option, widget)  # 必须最后调用

    def calculate(self, step=0):
        # ---------------------- 初始化计算常数 ----------------------------------
        # 给焊接弯头情况下不同管径的数组赋值
        X = [22.5, 30, 45, 60, 90]  # 弯头角度
        Y_弯管 = [0.07, 0.09, 0.12, 0.15, 0.2]  # 弯管对应的阻力系数
        Y_热压 = [0, 0, 0.16, 0.2, 0.25]  # 热压弯头的阻力系数
        Y_锻造 = [0, 0, 0, 0, 0.6]  # 锻造弯头的阻力系数

        # 焊接弯头在不同公称直径下的阻力系数
        Y100 = [0.16, 0.25, 0.28, 0.43, 0.55]
        Y125 = [0.14, 0.22, 0.24, 0.37, 0.48]
        Y150 = [0.12, 0.19, 0.21, 0.32, 0.41]
        Y200 = [0.1, 0.16, 0.18, 0.27, 0.35]
        Y250 = [0.09, 0.14, 0.16, 0.24, 0.3]  # 管径大于250时
        Y500 = [0.11, 0.18, 0.19, 0.31, 0.4]  # 管径大于500时
        # ---------------------- 初始化计算常数 ----------------------------------

        # ---------------------- 获取当前组件上已有的参数 ------------------------------
        p1 = self.get("P1", need_unit=True)
        t1 = self.get("T1", need_unit=True)
        h1 = self.get("H1", need_unit=True)
        m1 = self.get("M1", need_unit=True)
        p2 = self.get("P2", need_unit=True)
        t2 = self.get("T2", need_unit=True)
        h2 = self.get("H2", need_unit=True)
        m2 = self.get("M2", need_unit=True)

        self.make_equal(symbol_des='M', from_symbols=["M1", "M2"], step=step)

        弯头类型 = self.get("TYPE")
        转弯角度 = self.get("ANGLE", need_unit=True)
        if 转弯角度 is None:
            return f"组件{self.scene_id}缺少弯曲角度 --- break"  # --- break表示该错误会导致计算立即退出，而不是等待其他组件继续计算
        转弯角度 = 转弯角度.get_value_with_unit("°")  # 将单位转换为°
        DN = self.get("DN", need_unit=True)
        DI = self.get("DI", need_unit=True)
        if DI is None:
            return f"组件{self.scene_id}缺少管道内径 --- break"  # --- break表示该错误会导致计算立即退出，而不是等待其他组件继续计算
        DI = DI.get_value_with_unit("m")  # 将DI的单位转换为m

        # -------------------------------- 计算阻力系数 -------------------------------------
        计算类型 = self.get("CTYPE")

        局部阻力系数 = None
        if 弯头类型 == "弯管":
            if 转弯角度 is None:
                return f"组件{self.scene_id}缺少弯曲角度 --- break"  # --- break表示该错误会导致计算立即退出，而不是等待其他组件继续计算
            局部阻力系数 = interpolate_value_complex(x=转弯角度, x_list=X, y_list=Y_弯管)
        elif 弯头类型 == "热压弯管":
            if 转弯角度 is None:
                return f"组件{self.scene_id}缺少弯曲角度 --- break"  # --- break表示该错误会导致计算立即退出，而不是等待其他组件继续计算
            局部阻力系数 = interpolate_value_complex(x=转弯角度, x_list=X, y_list=Y_热压)
        elif 弯头类型 == "锻造弯管":
            局部阻力系数 = 0.6
        else:
            if 计算类型 == "1:R":
                R = self.get("R")
                ratio = R / DN
            else:
                ratio = self.get("R/DN")
            局部阻力系数 = 1
        # -------------------------------- 计算阻力系数 -------------------------------------

        # -------------------------------- 计算压损等其他参数 ----------------------------------
        # 判断流量或压损这两个参数是否有值，任意一个有数据，则当前组件可以完成计算，如果二者都没有数据，则分析当前组件前后的组件布置情况
        # 计算介质流速
        rho = get_rho_by_pt(p1, t1)  # kg/m3
        M = self.get("M", need_unit=True)
        if M is None:
            _ = None
        else:
            _ = self.get("M", need_unit=True).get_value_with_unit('kg/s') / rho  # m3/s
        if _ is not None:  # 如果质量流量有数据
            VM = Value(_ * 3600, VolumeFlow("m^3/h"))
            A = math.pi * DI * DI / 4  # m2
            velocity = _ / A  # m/s
            self.values.update({"Density": Value(rho, Density("kg/m^3")),
                                "Velocity": Value(velocity, Velocity("m/s")),
                                "A": Value(A, Area("m^2"))
                                })

            压损 = rho * velocity * velocity / 2 * 局部阻力系数 / 1000000  # MPa
            if p1 is None:
                p1 = Value(p2.get_value_with_unit("MPa") + 压损, Pressure("MPa"))

            if p2 is None:
                p2 = Value(p1.get_value_with_unit("MPa") - 压损, Pressure("MPa"))

            if t1 is None:
                h2 = get_h_by_pt(p2, t2)
                t1 = Value(get_t_by_ph(p1, h2), Temperature("℃"))
            if t2 is None:
                h1 = get_h_by_pt(p1, t1)
                t2 = Value(get_t_by_ph(p2, h1), Temperature("℃"))

            self.values.update(values={"K": Value(局部阻力系数, One()),
                                       "P1": p1,
                                       "P2": p2,
                                       "DP": Value(压损, Pressure("MPa")),
                                       "T1": t1,
                                       "T2": t2,
                                       "VM": VM,
                                       })

            return "done"
        else:  # 判断压损数据是否可用，可以则计算
            if p1 is not None and p2 is not None:
                ...
            else:
                # 假设流量进行计算
                # 取前一个组件的流量，如果前一个组件是分流器，则取分流器总流量的1/2。并记录影响当前组件流量的最原始分流器流量设置（sid, pid, 流量分配系数）
                ...
                self.get_prev_components()

    def get_series_components(self):
        series = [self]
        pre_comp: YkGraphicsItem = self.get_prev_components()

        while "分流器" not in pre_comp.NAME:
            series.insert(0, pre_comp)
        series.insert(0, pre_comp)  # 将最开始的分流器添加到序列中

        next_comp: YkGraphicsItem = self.get_next_components()
        while "混合器" not in next_comp.NAME:
            series.append(next_comp)
        series.append(next_comp)  # 将最后的混合器添加到序列中

        self.scene().flag_item.series = series  # 将当前结果保存到全局对象中
        return series

    def get_pre_spliter(self):
        """
        获取序列头步的分流器组件
        """
        series = self.get_series_components()
        spliter: YkGraphicsItem = series[0]
        spliter.get("M1IF")


def 等值粗糙度(管道类型) -> float:
    """
    参考《GB 50764 电厂动力管道设计规范》表格C.0.2

    :param 管道类型:
    :return: 返回各类管子的等值粗糙度，单位为mm
    """
    epsilon = 0.2591
    if 管道类型 == '冷拔钢管':
        epsilon = 0.0015
    elif 管道类型 == "普通钢管/熟铁管":
        epsilon = 0.0457
    elif 管道类型 == "涂沥青铸铁管":
        epsilon = 0.1220
    elif 管道类型 == "镀锌铸铁管":
        epsilon = 0.1524
    elif 管道类型 == "其他":
        epsilon = None
    return epsilon
