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


import com.jiayue.ipfcst.common.data.constant.enums.DataSourceEnum;
import com.jiayue.ipfcst.common.data.constant.enums.ElectricFieldTypeEnum;
import com.jiayue.ipfcst.common.data.constant.enums.EquipmentTypeEnum;
import com.jiayue.ipfcst.common.data.entity.ElectricField;
import com.jiayue.ipfcst.common.data.entity.InverterInfo;
import com.jiayue.ipfcst.common.data.entity.ProtocolGatherDataPoint;
import com.jiayue.ipfcst.common.data.entity.WindTurbineInfo;
import com.jiayue.ipfcst.console.service.ElectricFieldService;
import com.jiayue.ipfcst.console.service.InverterInfoService;
import com.jiayue.ipfcst.console.service.WindTurbineInfoService;
import com.jiayue.ipfcst.dataexchange.dataprocesser.datagainerhandler.BaseDataGainer;
import com.jiayue.ipfcst.dataexchange.dataprocesser.datagainerhandler.NumOrBool;
import com.jiayue.ipfcst.dataexchange.dataprocesser.datagainerhandler.iml.GetDataFromContainer;
import com.jiayue.ipfcst.dataexchange.dataprocesser.datagainerhandler.iml.PointDataCalculator;
import com.jiayue.ipfcst.dataexchange.dataprocesser.datapacker.powerofreference.BasePowerOfReferenceCalculator;
import com.jiayue.ipfcst.dataexchange.exception.DataExchangeException;
import com.jiayue.ipfcst.dataexchange.service.ProtocolGatherDataPointService;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 样板机的发电比例法计算     判断参照功率
 *
 *
 * @author: xiuwei
 * @version: 3.0
 */
@Setter
@Slf4j
public class PowerOfReferenceCalculator1 extends BasePowerOfReferenceCalculator {


  /**
   * 场站的总运行容量
   */
  BigDecimal stationTotalCapacity;


  /**
   * 样板机信息
   */
  List<SampleEquipment> equipments = new ArrayList<>();

  public PowerOfReferenceCalculator1(WindTurbineInfoService windTurbineInfoService, InverterInfoService inverterInfoService, ElectricFieldService electricFieldService, ProtocolGatherDataPointService protocolGatherDataPointService) {
    super(windTurbineInfoService, inverterInfoService, electricFieldService, protocolGatherDataPointService);
  }

  public void addSampleEquipment(@NonNull Integer equipmentId, @NonNull BigDecimal capacity, @NonNull ProtocolGatherDataPoint protocolGatherDataPoint) {
    SampleEquipment sample = new SampleEquipment();
    sample.setCapacity(capacity);
    sample.setEquipmentId(equipmentId);
    if (protocolGatherDataPoint != null) {
      if (DataSourceEnum.GATHER.equals(protocolGatherDataPoint.getDataSource())) {
        sample.gainer = new GetDataFromContainer(NumOrBool.NUM, protocolGatherDataPoint.getId(),BigDecimal.ONE.doubleValue());
      } else if (DataSourceEnum.GENERATE.equals(protocolGatherDataPoint.getDataSource())) {
        sample.gainer = new PointDataCalculator(NumOrBool.NUM, protocolGatherDataPoint.getGenerationRegulation(), protocolGatherDataPoint.getMagnification());
      }
    }
    this.equipments.add(sample);
  }

  /**
   * 获取预计的发电功率
   *
   * @return 预计的功率
   */
  @Override
  public BigDecimal getEstimatePower() {
    BigDecimal avgRatio = BigDecimal.ZERO;
    BigDecimal ratio = BigDecimal.ZERO;
    try {
      if (stationTotalCapacity != null && stationTotalCapacity.compareTo(BigDecimal.ZERO) != 0) {
        for (SampleEquipment e : equipments) {
          ratio=e.updatePower().getSamplePowerGenerationRatio();
          if(ratio.compareTo(BigDecimal.ONE)>0){
            log.warn("样板机"+e.equipmentId+"发电量超装");
          }
          if(ratio.compareTo(BigDecimal.ZERO)>0){
            avgRatio = avgRatio.add(ratio);
          }
        }
      }
      if (equipments.size() == 0) {
        return BigDecimal.ZERO;
      }
      avgRatio = avgRatio.divide(BigDecimal.valueOf(equipments.size()), 10, BigDecimal.ROUND_HALF_UP).multiply(stationTotalCapacity).setScale(2, BigDecimal.ROUND_HALF_UP);
    } catch (Exception e) {
      log.error("计算样板机法理论功率数据时发生了异常" + e);
    }
    return avgRatio;
  }

  @SneakyThrows
  @Override
  public BasePowerOfReferenceCalculator init() {
    ElectricField electricField = electricFieldService.getElectricField();
    this.electricFieldType = electricField.getElectricFieldTypeEnum();
    this.stationTotalCapacity = electricField.getCapacity();
    ProtocolGatherDataPoint point;
    if (ElectricFieldTypeEnum.E1.equals(this.electricFieldType)) {
      List<InverterInfo> inverterInfos = inverterInfoService.getAllSample();
      for (InverterInfo i : inverterInfos) {
        point = protocolGatherDataPointService.get(i.getId(), EquipmentTypeEnum.INVERTER, "activePower");
        if (point != null) {
          this.addSampleEquipment(i.getId(), i.getCapacity(), point);
        }
      }
    } else if (ElectricFieldTypeEnum.E2.equals(this.electricFieldType)) {
      List<WindTurbineInfo> windTurbineInfos = windTurbineInfoService.getAllSample();
      for (WindTurbineInfo i : windTurbineInfos) {
        point = protocolGatherDataPointService.get(i.getId(), EquipmentTypeEnum.WINDTURBINE, "activePower");
        if (point != null) {
          this.addSampleEquipment(i.getId(), BigDecimal.valueOf(i.getMaxPower()), point);
        }
      }
    }
    return this;
  }
}


/**
 * 样板机信息
 */
@Setter
@NoArgsConstructor
class SampleEquipment {
  /**
   * 设备ID
   */
  int equipmentId;
  /**
   * 设备实际功率
   */
  BigDecimal realPower;
  /**
   * 设备实际功率获取器
   */
  BaseDataGainer<BigDecimal> gainer;
  /**
   * 设备容量
   */
  BigDecimal capacity;


  /**
   * 样板机设备信息
   *
   * @param equipmentId 设备id
   * @param gainer      实际功率获得器
   * @param capacity    容量
   */
  public SampleEquipment(int equipmentId, BaseDataGainer<BigDecimal> gainer, BigDecimal capacity) {
    this.equipmentId = equipmentId;
    this.gainer = gainer;
    this.capacity = capacity;
  }

  /**
   * 获取发电比例
   *
   * @return 发电比例
   */
  protected BigDecimal getSamplePowerGenerationRatio() {
    return realPower.divide(capacity,2,BigDecimal.ROUND_HALF_UP);
  }

  /**
   * 更新实际功率数据
   *
   * @return 实例本身
   */
  public SampleEquipment updatePower() {
    if (this.gainer != null) {
      try {
        this.realPower = this.gainer.getData();
      } catch (DataExchangeException e) {
        e.printStackTrace();
      }
    }
    return this;
  }
}
