package com.nightscout.core.dexcom.records;
import com.nightscout.core.dexcom.Constants;
import com.nightscout.core.dexcom.InvalidRecordLengthException;
import com.nightscout.core.dexcom.TrendArrow;
import com.nightscout.core.dexcom.Utils;
import com.nightscout.core.model.G4Noise;
import com.nightscout.core.model.GlucoseUnit;
import com.nightscout.core.model.SensorGlucoseValueEntry;
import com.nightscout.core.utils.GlucoseReading;
import org.joda.time.DateTime;
import org.json.JSONException;
import org.json.JSONObject;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;
public class EGVRecord extends GenericTimestampRecord {
public final static int RECORD_SIZE = 12;
private GlucoseReading reading;
private TrendArrow trend;
private G4Noise noiseMode;
public EGVRecord(byte[] packet, long rcvrTime, long refTime) {
super(packet, rcvrTime, refTime);
if (packet.length != RECORD_SIZE) {
throw new InvalidRecordLengthException("Unexpected record size: " + packet.length +
". Expected size: " + RECORD_SIZE + ". Unparsed record: " + Utils.bytesToHex(packet));
}
int bGValue = ByteBuffer.wrap(packet).order(ByteOrder.LITTLE_ENDIAN).getShort(8) & Constants.EGV_VALUE_MASK;
this.reading = new GlucoseReading(bGValue, GlucoseUnit.MGDL);
byte trendAndNoise = ByteBuffer.wrap(packet).order(ByteOrder.LITTLE_ENDIAN).get(10);
int trendValue = trendAndNoise & Constants.EGV_TREND_ARROW_MASK;
byte noiseValue = (byte) ((trendAndNoise & Constants.EGV_NOISE_MASK) >> 4);
this.trend = TrendArrow.values()[trendValue];
this.noiseMode = G4Noise.values()[noiseValue];
setRecordType();
}
public EGVRecord(int bGValueMgdl, TrendArrow trend, DateTime displayTime, DateTime systemTime, G4Noise noise, DateTime wallTime) {
super(displayTime, systemTime, wallTime);
this.reading = new GlucoseReading(bGValueMgdl, GlucoseUnit.MGDL);
this.trend = trend;
this.noiseMode = noise;
setRecordType();
}
public EGVRecord(int bGValueMgdl, TrendArrow trend, long displayTime, long systemTime, G4Noise noise, long rcvrTime, long refTime) {
super(displayTime, systemTime, rcvrTime, refTime);
this.reading = new GlucoseReading(bGValueMgdl, GlucoseUnit.MGDL);
this.trend = trend;
this.noiseMode = noise;
setRecordType();
}
public EGVRecord(SensorGlucoseValueEntry sgv, long rcvrTime, long refTime) {
super(sgv.disp_timestamp_sec, sgv.sys_timestamp_sec, rcvrTime, refTime);
this.reading = new GlucoseReading(sgv.sgv_mgdl, GlucoseUnit.MGDL);
this.trend = TrendArrow.values()[sgv.trend.ordinal()];
this.noiseMode = sgv.noise;
setRecordType();
}
public static List<SensorGlucoseValueEntry> toProtobufList(List<EGVRecord> list) {
return toProtobufList(list, SensorGlucoseValueEntry.class);
}
protected void setRecordType() {
this.recordType = "sgv";
}
public int getBgMgdl() {
return reading.asMgdl();
}
public TrendArrow getTrend() {
return trend;
}
public G4Noise getNoiseMode() {
return noiseMode;
}
public JSONObject toJSON() throws JSONException {
JSONObject obj = new JSONObject();
obj.put("sgv", getBgMgdl());
obj.put("date", getWallTime());
return obj;
}
@Override
public SensorGlucoseValueEntry toProtobuf() {
SensorGlucoseValueEntry.Builder builder = new SensorGlucoseValueEntry.Builder();
return builder.sys_timestamp_sec(rawSystemTimeSeconds)
.disp_timestamp_sec(rawDisplayTimeSeconds)
.sgv_mgdl(reading.asMgdl())
.trend(trend.toProtobuf())
.noise(noiseMode)
.build();
}
public GlucoseReading getReading() {
return reading;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
EGVRecord egvRecord = (EGVRecord) o;
if (noiseMode != egvRecord.noiseMode) return false;
if (!reading.equals(egvRecord.reading)) return false;
return trend == egvRecord.trend;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + reading.hashCode();
result = 31 * result + trend.hashCode();
result = 31 * result + noiseMode.hashCode();
return result;
}
}