package com.jiayue.ipfcst.dataexchange.dataprocesser.datapacker;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.jiayue.ipfcst.common.data.entity.WindTurbineInfo;
import com.jiayue.ipfcst.common.data.entity.WindTurbineStatusData;
import com.jiayue.ipfcst.dataexchange.exception.DataExchangeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 机头风速法理论功率理论速度计算工厂
 *
 * @author 修唯
 * @date 2022/07/15
 */
@Slf4j
public class TheoreticalPowerByHubSpeedCalculateFactory {


  private final Map<Integer, TheoreticalPowerByHubSpeedCalculator> calculators = new ConcurrentHashMap<>();

  public void addWindTurbine(WindTurbineInfo windTurbineInfo) {
    if (windTurbineInfo == null) {
      return;
    }
    if (StringUtils.isEmpty(windTurbineInfo.getPowerCurveFunction())) {
      return;
    }
    try {
      calculators.put(windTurbineInfo.getId(), new TheoreticalPowerByHubSpeedCalculator(windTurbineInfo));
    } catch (DataExchangeException e) {
      log.error("{}创建机头风速法算法失败",windTurbineInfo.getName());
    }
  }


  private TheoreticalPowerByHubSpeedCalculateFactory() {
  }

  /**
   * 返回容器对象
   *
   * @return the instance
   */
  public static final TheoreticalPowerByHubSpeedCalculateFactory getInstance() {
    return TheoreticalPowerByHubSpeedCalculateFactory.LazyHolder.INSTANCE;
  }


  private static class LazyHolder {
    private static final TheoreticalPowerByHubSpeedCalculateFactory INSTANCE = new TheoreticalPowerByHubSpeedCalculateFactory();
  }


  public WindTurbineStatusData calculate(WindTurbineStatusData windTurbineStatusData) {
    if(calculators.containsKey(windTurbineStatusData.getEquipmentNo())){
      return calculators.get(windTurbineStatusData.getEquipmentNo()).calculate(windTurbineStatusData);
    }else{
      return windTurbineStatusData;
    }
  }

  /**
   * 机头风速法理论功率计算器
   *
   * @author 3377
   * @date 2022/07/15
   */

  public class TheoreticalPowerByHubSpeedCalculator {

    public TheoreticalPowerByHubSpeedCalculator(WindTurbineInfo windTurbineInfo) throws DataExchangeException {
      this.equipmentNo = windTurbineInfo.getId();
      this.function = windTurbineInfo.getPowerCurveFunction();
      try {
        this.compiledExp = AviatorEvaluator.compile(this.function);
      } catch (Exception e) {
        log.error("{}号风机的功率曲线公式解析失败，公式不可用", this.equipmentNo, e);
        throw new DataExchangeException(50001, "公式解析失败，公式不可用");
      }
      params.put(X, BigDecimal.ZERO);
      this.correctState=windTurbineInfo.getCorrectState();
    }

    private int equipmentNo;


    /**
     * 函数
     */
    private String function;


    /**
     * 函数转化为Aviator 可以使用的公式对象
     */
    Expression compiledExp;

    /**
     * 参数  代入到功率曲线函数中
     */
    private final Map<String, Object> params = new HashMap<>();


    /**
     * 未知数X  在功率函数中代表风速
     */
    private static final String X = "X";


    /**
     * 正确状态
     */
    private final Integer correctState;


    public WindTurbineStatusData calculate(WindTurbineStatusData windTurbineStatusData) {
      if (windTurbineStatusData.getWs() == null || windTurbineStatusData.getWs().compareTo(BigDecimal.valueOf(-99)) == 0) {
        return windTurbineStatusData;
      }
      if(!windTurbineStatusData.getStatus().equals(this.correctState)){
        windTurbineStatusData.setTheoreticalPowerByHubSpeed(BigDecimal.ZERO);
        return windTurbineStatusData;
      }
      params.put(X, windTurbineStatusData.getWs());
      String result = compiledExp.execute(params).toString();
      BigDecimal v;
      try {
        v = new BigDecimal(result).setScale(2, RoundingMode.HALF_UP);
        windTurbineStatusData.setTheoreticalPowerByHubSpeed(v);
      } catch (Exception e) {
       log.error("{}号风机机头风速法计算结果出错",this.equipmentNo);
      }
      return windTurbineStatusData;
    }


  }


}

