package com.device.comm.DGMS.algorithm;


import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import static com.device.comm.DGMS.algorithm.ReferenceManager.StringToDate;

public class Algorithm20
  implements AlgorithmConstant
{
  private ParamX X;
  private ArrayList<IValue> calIValue = new ArrayList();
  private IValueManager iValueManager;
  private ReferenceManager rfManager;
  
  public Algorithm20()
  {
    this.X = new ParamX();
    this.iValueManager = new IValueManager();
    this.rfManager = new ReferenceManager();
  }
  
  public IValue getInitParam()
  {
    return this.iValueManager.getPreIValue();
  }
  
  public void setInitParam(IValue iValue)
  {
    this.iValueManager.setPreIValue(iValue);
  }
  
  public void addRef(Double value, Date time)
  {
    this.rfManager.addReference(value.doubleValue(), time);
  }
  
  public Double calcBloodGlucose(double current, Date datetime) {
    Double bgValue = Double.valueOf(0.0D);
    IValue cur_data = new IValue(datetime, Double.valueOf(current));
    IValue i4_data = null;
    this.rfManager.findReference(datetime);
    if (this.rfManager.isCalK()) {
      i4_data = calKValueAlgorithm(cur_data);
    } else {
      i4_data = I4Algorith(cur_data);
    }
    if (this.rfManager.isCalK())
    {
      bgValue = Double.valueOf(this.rfManager.getRefValue().getValue());
    }
    else if (this.rfManager.isWaitCalK())
    {
      bgValue = Double.valueOf(this.rfManager.getRefValue().getValue());
      
      i4_data.setRfTime(this.rfManager.getRefValue().getTime());
      i4_data.setRf(Double.valueOf(this.rfManager.getRefValue().getValue()));
    }
    else if (i4_data.getK() != null)
    {
      bgValue = Double.valueOf(i4_data.getI4().doubleValue() / i4_data.getK().doubleValue());
    }
    bgValue = roundDouble(bgValue.doubleValue(), 1);
    if ((current >= 600.0D) || (current <= 30.0D)) {
      bgValue = Double.valueOf(0.0D);
    }
    i4_data.setBg(bgValue);
    this.iValueManager.setPreIValue(i4_data);
    
    String rft = i4_data.getRfTime() == null ? "" : dateformate(i4_data
      .getRfTime());
    
    System.out.println(i4_data.getCurrent() + "\t" + 
      dateformate(i4_data.getCurrentTime()) + "\t" + 
      bgValue);
    return bgValue;
  }

  private Double calcBloodGlucose(double current, int index) {
    Double bgValue = Double.valueOf(0.0D);
    IValue cur_data = new IValue(null, Double.valueOf(current));
    IValue i4_data = null;
    this.rfManager.findReference(index);
    if (this.rfManager.isCalK()) {
      i4_data = calKValueAlgorithm(cur_data);
    } else {
      i4_data = I4Algorith(cur_data);
    }


    if (this.rfManager.isCalK())
    {
      bgValue = Double.valueOf(this.rfManager.getRefValue().getValue());
    }
    else if (this.rfManager.isWaitCalK())
    {
      bgValue = Double.valueOf(this.rfManager.getRefValue().getValue());

      i4_data.setRfTime(this.rfManager.getRefValue().getTime());
      i4_data.setRf(Double.valueOf(this.rfManager.getRefValue().getValue()));
    }
    else if (i4_data.getK() != null)
    {
      bgValue = Double.valueOf(i4_data.getI4().doubleValue() / i4_data.getK().doubleValue());
    }
    bgValue = roundDouble(bgValue.doubleValue(), 1);
    if ((current >= 600.0D) || (current <= 30.0D)) {
      bgValue = Double.valueOf(0.0D);
    }
    i4_data.setBg(bgValue);
    this.iValueManager.setPreIValue(i4_data);
    this.calIValue.add(i4_data);
//    String rft = i4_data.getRfTime() == null ? "" : dateformate(i4_data
//            .getRfTime());
//
//    System.out.println(i4_data.getCurrent() + "\t" +
//            dateformate(i4_data.getCurrentTime()) + "\t" +
//            bgValue);
//    Log.d("RN_CAL",bgValue+"");
    return bgValue;
  }


  /*
   * index: 开始序号
   * refValue:参比血糖值
   * values:动态血糖数值列表
   */
  public ArrayList<Double> calculateBloodGlucose(int index, Double refValue, ArrayList<Double> values){

    rfManager.addCurrentReference(refValue,index);
//
    ArrayList<Double> dataList = new ArrayList<>();
//
    for(int i=0;i<values.size();i++){
      Double electricValue = values.get(i);
      Double bgValue = calcBloodGlucose(electricValue,index+i);
      dataList.add(bgValue);
    }

    return dataList;

//    Date startDate = StringToDate("2017/03/25 15:28:00");
//    addRef(refValue,startDate);
//
//    for(int i=1;i<values.size();i++){
//      Double electricValue = values.get(i);
//      Double bgValue = calcBloodGlucose(electricValue,new Date(startDate.getTime()+3*60*1000*i));
//      dataList.add(bgValue);
//    }
//
//    return dataList;

  }
  
  public IValue calTest(double current, Date datetime)
  {
    Double bgValue = Double.valueOf(0.0D);
    IValue cur_data = new IValue(datetime, Double.valueOf(current));
    IValue i4_data = null;
    this.rfManager.findReference(datetime);
    if (this.rfManager.isCalK()) {
      i4_data = calKValueAlgorithm(cur_data);
    } else {
      i4_data = I4Algorith(cur_data);
    }
    if (this.rfManager.isCalK())
    {
      bgValue = Double.valueOf(this.rfManager.getRefValue().getValue());
    }
    else if (this.rfManager.isWaitCalK())
    {
      bgValue = Double.valueOf(this.rfManager.getRefValue().getValue());
      
      i4_data.setRfTime(this.rfManager.getRefValue().getTime());
      i4_data.setRf(Double.valueOf(this.rfManager.getRefValue().getValue()));
    }
    else if (i4_data.getK() != null)
    {
      bgValue = Double.valueOf(i4_data.getI4().doubleValue() / i4_data.getK().doubleValue());
    }
    bgValue = roundDouble(bgValue.doubleValue(), 1);
    if ((current >= 600.0D) || (current <= 30.0D)) {
      bgValue = Double.valueOf(0.0D);
    }
    i4_data.setBg(bgValue);
    this.iValueManager.setPreIValue(i4_data);
    String rft = i4_data.getRfTime() == null ? "" : dateformate(i4_data
      .getRfTime());
    
    System.out.println(i4_data.getI0() + "\t" + i4_data.getI1() + "\t" + 
      i4_data.getI2() + "\t" + i4_data.getI3() + "\t" + 
      i4_data.getI4() + " \t " + i4_data.getK() + "\t " + 
      i4_data.getRf() + "\t" + i4_data.getBg() + 
      i4_data.getCurrent() + "\t" + 
      dateformate(i4_data.getCurrentTime()) + "\t" + 
      i4_data.getRf() + " \t" + rft);
    return i4_data;
  }
  
  private IValue calKValueAlgorithm(IValue cur_data)
  {
    Double kValue = Double.valueOf(0.0D);
    cur_data = calI4ForK(cur_data);
    kValue = cur_data.getK();
    I4Algorithm i4Temp = null;
    if ((kValue.doubleValue() >= 10.0D) && (kValue.doubleValue() <= 20.0D))
    {
      cur_data.setK(kValue);
      return cur_data;
    }
    if (kValue.doubleValue() < 10.0D)
    {
      cur_data.setI4(Double.valueOf(cur_data.getI3().doubleValue() - I4Algorithm.I4_20.getValue()));
      kValue = Double.valueOf(cur_data.getI4().doubleValue() / this.rfManager.getRefValue().getValue());
      i4Temp = I4Algorithm.I4_20;
    }
    else if (kValue.doubleValue() > 20.0D)
    {
      cur_data.setI4(Double.valueOf(cur_data.getI3().doubleValue() - I4Algorithm.I4_60.getValue()));
      kValue = Double.valueOf(cur_data.getI4().doubleValue() / this.rfManager.getRefValue().getValue());
      i4Temp = I4Algorithm.I4_60;
    }
    if ((kValue.doubleValue() >= 7.5D) && (kValue.doubleValue() <= 25.0D))
    {
      cur_data.setK(kValue);
      cur_data.setBgCurrent(i4Temp.getValue());
      return cur_data;
    }
    if (kValue.doubleValue() < 7.5D)
    {
      cur_data.setI4(Double.valueOf(cur_data.getI3().doubleValue() - I4Algorithm.I4_0.getValue()));
      kValue = Double.valueOf(cur_data.getI4().doubleValue() / this.rfManager.getRefValue().getValue());
      i4Temp = I4Algorithm.I4_0;
    }
    else if (kValue.doubleValue() > 25.0D)
    {
      cur_data.setI4(Double.valueOf(cur_data.getI3().doubleValue() - I4Algorithm.I4_80.getValue()));
      kValue = Double.valueOf(cur_data.getI4().doubleValue() / this.rfManager.getRefValue().getValue());
      i4Temp = I4Algorithm.I4_80;
    }
    if ((2.5D < kValue.doubleValue()) && 
      (kValue.doubleValue() < 40.0D))
    {
      cur_data.setK(kValue);
      cur_data.setBgCurrent(i4Temp.getValue());
    }
    return cur_data;
  }

    public int calRoc() {
        if (this.calIValue == null) {
            return 0;
        }
        int size = this.calIValue.size();
        if (size == 0 || size <= 2) {
            return 0;
        }
        double b0 = ((IValue) this.calIValue.get(size - 3)).getBg().doubleValue();
        double b1 = ((IValue) this.calIValue.get(size - 2)).getBg().doubleValue();
        double b2 = ((IValue) this.calIValue.get(size - 1)).getBg().doubleValue();
        if (b0 == 0.0d || b1 == 0.0d || b2 == 0.0d) {
            return 0;
        }
        double roc = (0.3d * ((b1 - b0) / 3.0d)) + (0.7d * ((b2 - b1) / 3.0d));
        if (roc >= 0.1d) {
            return 1;
        }
        if (roc > 0.05d && roc < 0.1d) {
            return 2;
        }
        if (roc >= -0.05d && roc <= 0.05d) {
            return 3;
        }
        if (roc > -0.1d && roc < -0.05d) {
            return 4;
        }
        if (roc <= -0.1d) {
            return 5;
        }
        return 0;
    }
  
  private IValue calI4ForK(IValue cur_data)
  {
    IValue I4_redta = I4Algorith(cur_data);
    
    Double kValue = Double.valueOf(I4_redta.getI4().doubleValue() / 
      this.rfManager.getRefValue().getValue());
    I4_redta.setK(kValue);
    
    return I4_redta;
  }
  
  private IValue I4Algorith(IValue cur_data)
  {
    IValue prev_data = this.iValueManager.getPreIValue();
    
    cur_data.setI0(cur_data.getCurrent());
    
    cur_data.setI1(
      Double.valueOf(cur_data.getI0().doubleValue() * (1.0D + this.X.X1 * (32.0D - this.X.X2))));
    if ((prev_data != null) && (prev_data.getI3() != null))
    {
      cur_data.setI3(
        Double.valueOf(this.X.X4 * cur_data.getI1().doubleValue() + (1.0D - this.X.X4) * prev_data.getI3().doubleValue()));
      
      cur_data.setBgCurrent(prev_data.getBgCurrent());
      cur_data.setK(prev_data.getK());
      if ((cur_data.getRf() != null) && (cur_data.getRf().doubleValue() != 0.0D))
      {
        cur_data.setRf(prev_data.getRf());
        cur_data.setRfTime(prev_data.getRfTime());
      }
    }
    else
    {
      cur_data.setBgCurrent(I4Algorithm.I4_40.getValue());
      cur_data.setI3(cur_data.getI1());
    }
    cur_data.setI4(Double.valueOf(cur_data.getI3().doubleValue() - cur_data.getBgCurrent()));
    
    return cur_data;
  }
  
  private Double roundDouble(double val, int precision)
  {
    Double ret = null;
    try
    {
      double factor = Math.pow(10.0D, precision);
      ret = Double.valueOf(Math.floor(val * factor + 0.5D) / factor);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    return ret;
  }
  
  private String dateformate(Date date)
  {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return formatter.format(date);
  }
}

