package com.ruoyi.caltools.controller;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.caltools.model.FlowProps;
import com.ruoyi.caltools.model.GasProps;
import com.ruoyi.caltools.service.DetailService;
import com.ruoyi.caltools.service.GBT11062Service;
import com.ruoyi.caltools.service.ThermService;
import com.ruoyi.system.controller.UnitConvert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static com.ruoyi.caltools.controller.DpFlowCalc.iterativeFlowCalculation;
import static com.ruoyi.caltools.controller.DpFlowCalc.thermalExpansionCorrection;

@RestController
@RequestMapping("/flowCalTools")
public class FlowController {
    @Autowired
    private ThermService thermService;
    @Autowired
    private DetailService detailService;
    @Autowired
    private GBT11062Service gbt11062Service;
    @Autowired
    private GasController gasController;
    @Autowired
    private UnitConvert unitConvert;
    @Autowired
    private NozellFlowCalcISO9300 nozellFlowCalcISO9300;
    @PostMapping("/flowCalc")
    public AjaxResult flowCalc(@RequestBody FlowProps flowProps) {
        GasProps gasProps = new GasProps();


        //大气压力转换成Pa
        double tempPatm = unitConvert.ConvertUniter("pressure", flowProps.getdPatm(), flowProps.getdPatmUnit(), 0);
        //压力转换成Pa
        double tempPf = unitConvert.ConvertUniter("pressure", flowProps.getdPf(), flowProps.getdPfUnit(), 0);

        //压力转换成Pa
        double tempDP = unitConvert.ConvertUniter("pressure", flowProps.getdDp(), flowProps.getdDpUnit(), 0);
        //温度转换成K
        double tempTf = unitConvert.ConvertUniter("temperature", flowProps.getdTf(), flowProps.getdTfUnit(), 2);
        if (flowProps.getdPfType() == 0)  //0是表压
        {
            gasProps.dPf = tempPatm + tempPf;
            flowProps.setdPf(tempPatm + tempPf);
        } else {
            gasProps.dPf = tempPf;
            flowProps.setdPf(tempPf);
        }
        gasProps.dTf = tempTf;
        flowProps.setdDp(tempDP);
        flowProps.setdTf(tempTf);

        gasProps.dCbtj = flowProps.getdCbtj();
        switch (gasProps.dCbtj)
        {
            case 2:
                gasProps.setdPb(101325);
                gasProps.setdTb( 273.15);
                flowProps.setdPb_M(101325);
                flowProps.setdTb_M(273.15);
                break;
            case 1:

                gasProps.setdPb(101325);
                gasProps.setdTb( 288.15);
                flowProps.setdPb_M(101325);
                flowProps.setdTb_M(288.15);
                break;
            case 0:

                gasProps.setdPb(101325);
                gasProps.setdTb( 293.15);
                flowProps.setdPb_M(101325);
                flowProps.setdTb_M(293.15);
                break;
        }

        String[] stringArray = flowProps.getdngComponents().split("_");
        double[] doubleArray = new double[stringArray.length];        // 遍历字符串数组，将每个元素转换为 double 类型
        for (int i = 0; i < stringArray.length; i++) {
            try {
                doubleArray[i] = Double.parseDouble(stringArray[i]) / 100;
            } catch (NumberFormatException e) {
                // 处理转换异常
                System.err.println("无法将字符串 " + stringArray[i] + " 转换为 double 类型: " + e.getMessage());
            }
        }
        gasProps.adMixture = doubleArray;
        GasController.ngCalcVoid(flowProps, gasProps); //计算临界流函数所有参数都计算了

        //计算流量
        switch (flowProps.getdMeterType()) {
            case 0: //差压式流量计
                // 执行计算
              thermalExpansionCorrection(flowProps); // 热膨胀修正
               iterativeFlowCalculation(flowProps, gasProps);

                //OFlowCal(gasProps,flowProps);
                break;
            case 1:// 速度式流量计
                SdFlowCal(gasProps, flowProps);
                break;
            case 2: //容积式流量计
                SdFlowCal(gasProps, flowProps);
                break;
            case 3:// 临界流函数流量计
                nozellFlowCalcISO9300.   calculateFlowCoefficient(flowProps,gasProps);
                break;
        }
        Object[] resultArray = {flowProps, gasProps};
        return AjaxResult.success(resultArray);
    }
    /**
     速度式流量计算
     */
    public static final void SdFlowCal(GasProps gasProps, FlowProps flowProps)
    {
        //工况体积流量 m³、s
        flowProps.setdVFlowf(flowProps.getdPulseNum() / flowProps.getdMeterFactor());
        //标况体积流量 m³、s
        flowProps.setdVFlowb(FlowConvert_WorkToBase(flowProps, gasProps));
        //标况质量流量
        flowProps.setdMFlowb(flowProps.getdVFlowb() * gasProps.dRhob);
        //标况能量流量
        flowProps.setdEFlowb(flowProps.getdVFlowb() * gasProps.dHhvm);

    }

    public final void NozellFLowCal_New(GasProps gasProps, FlowProps flowProps) {
        double nozzleThroatArea;   // 喷嘴喉部面积
        double stagnationPressure; // 滞止压力 P0
        double stagnationTemp;     // 滞止温度 T0
        double correctedPipeDiam;  // 修正后管道直径
        double correctedThroatDiam;// 修正后喉部直径
        double beta;               // 直径比 β = d/D
        double massFlowRate;       // 质量流量 Qm

        try {
            // 1. 热膨胀修正
            correctedThroatDiam = flowProps.getdOrificeD()
                    * (1 + 1e-6 * flowProps.getdOrificeMaterial() * (flowProps.getdTf() - 293.15));
            correctedPipeDiam = flowProps.getdPipeD()
                    * (1 + 1e-6 * flowProps.getdPipeMaterial() * (flowProps.getdTf() - 293.15));
            beta = correctedThroatDiam / correctedPipeDiam;

            // 2. 计算喉部面积
            nozzleThroatArea = Math.PI * Math.pow(correctedThroatDiam / 2, 2);

            // 3. 计算马赫数 (假设流速来自flowProps)
            double velocity = flowProps.getdVelocityFlow();
            double speedOfSound = Math.sqrt(gasProps.dKappa * gasProps.dZf
                    * 8314.51 / gasProps.dMrx * flowProps.getdTf());
            double machNumber = velocity / speedOfSound;

            // 4. 滞止压力 & 温度 (ISO 9300)
            stagnationPressure = flowProps.getdPf()
                    * Math.pow(1 + (gasProps.dKappa - 1)/2 * machNumber*machNumber,
                    gasProps.dKappa/(gasProps.dKappa - 1));
            stagnationTemp = flowProps.getdTf()
                    * (1 + (gasProps.dKappa - 1)/2 * machNumber*machNumber);

            // 5. 计算质量流量
            double gasConstant = 8314.51 / gasProps.dMrx;
            massFlowRate = nozzleThroatArea * flowProps.getdCd()
                    * Math.sqrt(gasProps.dKappa / (gasConstant * stagnationTemp))
                    * stagnationPressure
                    * Math.pow(2/(gasProps.dKappa + 1), (gasProps.dKappa + 1)/(2*(gasProps.dKappa - 1)));

            // 6. 大直径比修正
            if (beta > 0.25) {
                massFlowRate *= BetaG25(stagnationPressure, stagnationTemp, beta, gasProps);
            }

            // 7. 设置结果
            flowProps.setdMFlowb(massFlowRate);
            flowProps.setdVFlowb(massFlowRate / gasProps.dRhob);
            flowProps.setdEFlowb(flowProps.getdVFlowb() * gasProps.dHhvm);
            flowProps.setdVFlowf(FlowConvert_BaseToWork(flowProps, gasProps));

        } catch (Exception ex)
        {
        }
    }


    

    /**
     天然气音速喷嘴流量计算
     */
    public final void NozellFLowCal( GasProps gasProps,FlowProps flowProps)
    {
        double dAnt; // 喷嘴喉部面积
        //double dCR;//临界流系数
        double dP1Z; //滞止压力
        double dT1Z; //滞止温度
        //double dPbeta;//上下游压力比
        double dDcorrect; // 考虑膨胀系数后的管道直径
        double ddcorrect; // 考虑膨胀系数后的喉部直径
        double dBeta; //直径比
        double dQm;
        try
        {
            ddcorrect = flowProps.getdOrificeD() * (1 + 0.000001 * (flowProps.getdOrificeMaterial()) * (flowProps.getdTf() - 293.15));
            dDcorrect = flowProps.getdPipeD() * (1 + 0.000001 * (flowProps.getdOrificeMaterial()) * (flowProps.getdTf() - 293.15));
            dBeta = ddcorrect / dDcorrect;
            dAnt = 3.1415926 * (ddcorrect / 2) * (ddcorrect / 2);
            //ptNGcal.SOS(ref gasProps);

            //dCR = gasProps.dCstar * Math.Sqrt(gasProps.dZf);
            dP1Z = flowProps.getdPf() * (1 + gasProps.dKappa / 2 * Math.pow((2 / (gasProps.dKappa + 1)), ((gasProps.dKappa + 1) / (gasProps.dKappa - 1))) * Math.pow(dBeta, 4));
            dT1Z = flowProps.getdTf() * (1 + (gasProps.dKappa - 1) / 2 * (2 / Math.pow((gasProps.dKappa + 1), ((gasProps.dKappa + 1) / (gasProps.dKappa - 1)))) * Math.pow(dBeta, 4));
            // dQm = dAnt * flowProps.dCd * gasProps.dCstar * dP1Z / Math.Sqrt(8314.51 * dT1Z / gasProps.dMrx);
            dQm = dAnt * flowProps.getdCd() * gasProps.dCstar * Math.sqrt(gasProps.dZf * dP1Z * gasProps.dRhof);

            if (dBeta > 0.25)
            {
                dQm = dQm * BetaG25(dP1Z, dT1Z, dBeta, gasProps);
            }
            flowProps.setdMFlowb(dQm);
            flowProps.setdVFlowb(flowProps.getdMFlowb() / gasProps.dRhob);
            //标况能量流量
            flowProps.setdEFlowb(flowProps.getdVFlowb() * gasProps.dHhvm);
            flowProps.setdVFlowf(FlowConvert_BaseToWork(flowProps, gasProps));
        }
        catch (RuntimeException ex)
        {

        }
    }

    private double BetaG25(double P0, double T0, double BetaB, GasProps gasProps)
    {
        double[] nik0 = new double[9];
        double[] Sik0 = new double[9];
        double[] Tik0 = new double[9];
        double[] nik1 = new double[9];
        double[] Sik1 = new double[9];
        double[] Tik1 = new double[9];
        double C0 = 0;
        double C1 = 0;
        double Pai ;
        double Tuo ;
        double b ;
        double F0 ;
        double F1 ;
        double Rf = 0.65;
        // 直径比大于0.25的修正因子
        nik0[0] = 1.068826e-3;
        nik0[1] = 1.199593e-2;
        nik0[2] = -1.48292e-3;
        nik0[3] = 2.764799e-4;
        nik0[4] = 7.920711e-5;
        nik0[5] = 1.11278e-3;
        nik0[6] = -6.815626e-5;
        nik0[7] = 3.86249e-8;

        nik1[0] = -3.46148e-3;
        nik1[1] = 5.28029e-3;
        nik1[2] = 1.195016e-2;
        nik1[3] = 1.664232e-3;
        nik1[4] = 1.159371e-3;
        nik1[5] = 7.260461e-3;
        nik1[6] = -7.541933e-4;
        nik1[7] = 2.613967e-7;

        Sik0[0] = 0;
        Sik0[1] = 0;
        Sik0[2] = 0.5;
        Sik0[3] = 1;
        Sik0[4] = 2;
        Sik0[5] = 3;
        Sik0[6] = 5;
        Sik0[7] = 10;

        Sik1[0] = 0;
        Sik1[1] = 0;
        Sik1[2] = 0;
        Sik1[3] = 1;
        Sik1[4] = 1.5;
        Sik1[5] = 3;
        Sik1[6] = 5;
        Sik1[7] = 10;

        Tik0[0] = -1;
        Tik0[1] = 0;
        Tik0[2] = -6;
        Tik0[3] = -1;
        Tik0[4] = -2;
        Tik0[5] = -8;
        Tik0[6] = -10;
        Tik0[7] = -18;

        Tik1[0] = -3;
        Tik1[1] = -1;
        Tik1[2] = 0;
        Tik1[3] = -2;
        Tik1[4] = -4;
        Tik1[5] = -10;
        Tik1[6] = -12;
        Tik1[7] = -15;

        Pai = P0 / (gasProps.dPc * 1000000);
        Tuo = T0 / gasProps.dTC;
        for (int i = 0; i <= 7; i += 1)
        {
            C0 = C0 + nik0[i] * Math.pow(Pai, Sik0[i]) * Math.pow(Tuo, Tik0[i]);
            C1 = C1 + nik1[i] * Math.pow(Pai, Sik1[i]) * Math.pow(Tuo, Tik1[i]);
        }
        b = 25.879 * Math.pow(BetaB, 6) - 32.693 * Math.pow(BetaB, 5) + 34.276 * Math.pow(BetaB, 4) - 6.0199 * Math.pow(BetaB, 3) - 1.1156 * Math.pow(BetaB, 2) - 0.1122 * BetaB + 0.0047;
        F0 = 1 + b * C0;
        F1 = 1 + b * C1;
        return (1 - Rf) * F0 + Rf * F1;
    }

    //压力损失计算
    public static final double YaLiSunShi(double tempLiuChuXiShu, double tempZjb, double tempDp, int JieLiuZhuangZhi)
    {
        double ylss = 0;
        switch (JieLiuZhuangZhi)
        {
            case 0:
                ylss = (tempDp * (Math.sqrt(1 - tempZjb) - tempLiuChuXiShu * Math.pow(tempZjb, 2)) / (Math.sqrt(1 - tempZjb) + tempLiuChuXiShu * Math.pow(tempZjb, 2)));
                break;
            case 1:
                ylss = (tempDp * (Math.sqrt(1 - tempZjb) - tempLiuChuXiShu * Math.pow(tempZjb, 2)) / (Math.sqrt(1 - tempZjb) + tempLiuChuXiShu * Math.pow(tempZjb, 2)));
                break;
            case 2:
                ylss = (tempDp * (Math.sqrt(1 - tempZjb) - tempLiuChuXiShu * Math.pow(tempZjb, 2)) / (Math.sqrt(1 - tempZjb) + tempLiuChuXiShu * Math.pow(tempZjb, 2)));
                break;
        }
        return ylss;
    }


    // #########################################################################
    // ######################'流量转换  标况转工况##############################
    // ########################################################################
    public static double FlowConvert_BaseToWork(FlowProps flowProps, GasProps gasProps)
    {
        double tempPn = 0;
        double tempTn = 0;

        try
        {

            if (gasProps.dZf == 0 || gasProps.dZb == 0)
            {
                return 0.0;
            }


            switch (gasProps.dCbtj)
            {
                case 2:
                    tempPn = 101325;
                    tempTn = 273.15;
                    break;

                case 1:
                    tempPn = 101325;
                    tempTn = 288.15;
                    break;

                case 0:
                    tempPn = 101325;
                    tempTn = 293.15;
                    break;

                case 3:
                    tempPn = 10155981;
                    tempTn = 288.7055555;
                    break;
            }


            flowProps.setdVFlowf(flowProps.getdVFlowb() * (tempPn * flowProps.getdTf() * gasProps.dZf) / (flowProps.getdPf() * tempTn * gasProps.dZb));
            return flowProps.getdVFlowf();
            // WARNING: ErrDo: is not supported 
        }
        catch (RuntimeException exc)
        {
            return 0.0;

        }
    }

    // #########################################################################
    // ######################流量转换工况转标况##############################
    // ########################################################################
    public static double FlowConvert_WorkToBase(FlowProps flowProps, GasProps gasProps)
    {
        double tempPn = 0;
        double tempTn = 0;

        // WARNING: On Error GOTO ErrDo is not supported
        try
        {

            switch (gasProps.dCbtj)
            {
                case 2:
                    tempPn = 101325;
                    tempTn = 273.15;
                    break;

                case 1:
                    tempPn = 101325;
                    tempTn = 288.15;
                    break;

                case 0:
                    tempPn = 101325;
                    tempTn = 293.15;
                    break;

                case 3:
                    tempPn = 0.10155981;
                    tempTn = 288.7055555;
                    break;
            }
            flowProps.setdVFlowb(flowProps.getdVFlowf() * (flowProps.getdPf() * tempTn * gasProps.dZb) / (tempPn * flowProps.getdTf() * gasProps.dZf));
            return flowProps.getdVFlowb();
            // WARNING: ErrDo: is not supported 
        }
        catch (RuntimeException exc)
        {
            return 0.0;
        }

    }

    public ThermService getThermService() {
        return thermService;
    }

    public DetailService getDetailService() {
        return detailService;
    }

    public GBT11062Service getGbt11062Service() {
        return gbt11062Service;
    }

    public GasController getGasController() {
        return gasController;
    }
}
