package com.eveningoutpost.dexdrip.UtilityModels;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Color;
import android.preference.PreferenceManager;
import android.text.format.DateFormat;
import com.eveningoutpost.dexdrip.Models.BgReading;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.Utils;
import lecho.lib.hellocharts.view.Chart;
/**
* Created by stephenblack on 11/15/14.
*/
public class BgGraphBuilder {
public int fuzzer = (1000 * 30 * 5);
public double end_time = (new Date().getTime() + (60000 * 10)) / fuzzer;
public double start_time = end_time - ((60000 * 60 * 24)) / fuzzer;
public Context context;
public SharedPreferences prefs;
public double highMark;
public double lowMark;
public double defaultMinY;
public double defaultMaxY;
public boolean doMgdl;
final int pointSize;
final int axisTextSize;
final int previewAxisTextSize;
final int hoursPreviewStep;
private double endHour;
private final int numValues =(60/5)*24;
private final List<BgReading> bgReadings = BgReading.latestForGraph( numValues, (start_time * fuzzer));
private List<PointValue> inRangeValues = new ArrayList<PointValue>();
private List<PointValue> highValues = new ArrayList<PointValue>();
private List<PointValue> lowValues = new ArrayList<PointValue>();
private List<PointValue> rawInterpretedValues = new ArrayList<PointValue>();
public Viewport viewport;
public BgGraphBuilder(Context context){
this.context = context;
this.prefs = PreferenceManager.getDefaultSharedPreferences(context);
this.highMark = Double.parseDouble(prefs.getString("highValue", "170"));
this.lowMark = Double.parseDouble(prefs.getString("lowValue", "70"));
this.doMgdl = (prefs.getString("units", "mgdl").compareTo("mgdl") == 0);
defaultMinY = unitized(40);
defaultMaxY = unitized(250);
pointSize = isXLargeTablet() ? 5 : 3;
axisTextSize = isXLargeTablet() ? 20 : Axis.DEFAULT_TEXT_SIZE_SP;
previewAxisTextSize = isXLargeTablet() ? 12 : 5;
hoursPreviewStep = isXLargeTablet() ? 2 : 1;
}
public LineChartData lineData() {
LineChartData lineData = new LineChartData(defaultLines());
lineData.setAxisYLeft(yAxis());
lineData.setAxisXBottom(xAxis());
return lineData;
}
public LineChartData previewLineData() {
LineChartData previewLineData = new LineChartData(lineData());
previewLineData.setAxisYLeft(yAxis());
previewLineData.setAxisXBottom(previewXAxis());
previewLineData.getLines().get(4).setPointRadius(2);
previewLineData.getLines().get(5).setPointRadius(2);
previewLineData.getLines().get(6).setPointRadius(2);
return previewLineData;
}
public List<Line> defaultLines() {
addBgReadingValues();
List<Line> lines = new ArrayList<Line>();
lines.add(minShowLine());
lines.add(maxShowLine());
lines.add(highLine());
lines.add(lowLine());
lines.add(inRangeValuesLine());
lines.add(lowValuesLine());
lines.add(highValuesLine());
lines.add(rawInterpretedLine());
return lines;
}
public Line highValuesLine() {
Line highValuesLine = new Line(highValues);
highValuesLine.setColor(Utils.COLOR_ORANGE);
highValuesLine.setHasLines(false);
highValuesLine.setPointRadius(pointSize);
highValuesLine.setHasPoints(true);
return highValuesLine;
}
public Line lowValuesLine() {
Line lowValuesLine = new Line(lowValues);
lowValuesLine.setColor(Color.parseColor("#C30909"));
lowValuesLine.setHasLines(false);
lowValuesLine.setPointRadius(pointSize);
lowValuesLine.setHasPoints(true);
return lowValuesLine;
}
public Line inRangeValuesLine() {
Line inRangeValuesLine = new Line(inRangeValues);
inRangeValuesLine.setColor(Utils.COLOR_BLUE);
inRangeValuesLine.setHasLines(false);
inRangeValuesLine.setPointRadius(pointSize);
inRangeValuesLine.setHasPoints(true);
return inRangeValuesLine;
}
public Line rawInterpretedLine() {
Line line = new Line(rawInterpretedValues);
line.setHasLines(false);
line.setPointRadius(1);
line.setHasPoints(true);
return line;
}
private void addBgReadingValues() {
for (BgReading bgReading : bgReadings) {
if (bgReading.raw_calculated != 0 && prefs.getBoolean("interpret_raw", false)) {
rawInterpretedValues.add(new PointValue((float) (bgReading.timestamp/fuzzer), (float) unitized(bgReading.raw_calculated)));
} else if (bgReading.calculated_value >= 400) {
highValues.add(new PointValue((float) (bgReading.timestamp/fuzzer), (float) unitized(400)));
} else if (unitized(bgReading.calculated_value) >= highMark) {
highValues.add(new PointValue((float) (bgReading.timestamp/fuzzer), (float) unitized(bgReading.calculated_value)));
} else if (unitized(bgReading.calculated_value) >= lowMark) {
inRangeValues.add(new PointValue((float) (bgReading.timestamp/fuzzer), (float) unitized(bgReading.calculated_value)));
} else if (bgReading.calculated_value >= 40) {
lowValues.add(new PointValue((float)(bgReading.timestamp/fuzzer), (float) unitized(bgReading.calculated_value)));
} else if (bgReading.calculated_value > 13) {
lowValues.add(new PointValue((float)(bgReading.timestamp/fuzzer), (float) unitized(40)));
}
}
}
public Line highLine() {
List<PointValue> highLineValues = new ArrayList<PointValue>();
highLineValues.add(new PointValue((float)start_time, (float)highMark));
highLineValues.add(new PointValue((float)end_time, (float)highMark));
Line highLine = new Line(highLineValues);
highLine.setHasPoints(false);
highLine.setStrokeWidth(1);
highLine.setColor(Utils.COLOR_ORANGE);
return highLine;
}
public Line lowLine() {
List<PointValue> lowLineValues = new ArrayList<PointValue>();
lowLineValues.add(new PointValue((float)start_time, (float)lowMark));
lowLineValues.add(new PointValue((float)end_time, (float)lowMark));
Line lowLine = new Line(lowLineValues);
lowLine.setHasPoints(false);
lowLine.setAreaTransparency(50);
lowLine.setColor(Color.parseColor("#C30909"));
lowLine.setStrokeWidth(1);
lowLine.setFilled(true);
return lowLine;
}
public Line maxShowLine() {
List<PointValue> maxShowValues = new ArrayList<PointValue>();
maxShowValues.add(new PointValue((float)start_time, (float)defaultMaxY));
maxShowValues.add(new PointValue((float)end_time, (float)defaultMaxY));
Line maxShowLine = new Line(maxShowValues);
maxShowLine.setHasLines(false);
maxShowLine.setHasPoints(false);
return maxShowLine;
}
public Line minShowLine() {
List<PointValue> minShowValues = new ArrayList<PointValue>();
minShowValues.add(new PointValue((float)start_time, (float)defaultMinY));
minShowValues.add(new PointValue((float)end_time, (float)defaultMinY));
Line minShowLine = new Line(minShowValues);
minShowLine.setHasPoints(false);
minShowLine.setHasLines(false);
return minShowLine;
}
/////////AXIS RELATED//////////////
public Axis yAxis() {
Axis yAxis = new Axis();
yAxis.setAutoGenerated(false);
List<AxisValue> axisValues = new ArrayList<AxisValue>();
for(int j = 1; j <= 12; j += 1) {
if (doMgdl) {
axisValues.add(new AxisValue(j * 50));
} else {
axisValues.add(new AxisValue(j*2));
}
}
yAxis.setValues(axisValues);
yAxis.setHasLines(true);
yAxis.setMaxLabelChars(5);
yAxis.setInside(true);
yAxis.setTextSize(axisTextSize);
return yAxis;
}
public Axis xAxis() {
Axis xAxis = new Axis();
xAxis.setAutoGenerated(false);
List<AxisValue> xAxisValues = new ArrayList<AxisValue>();
GregorianCalendar now = new GregorianCalendar();
GregorianCalendar today = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH));
final java.text.DateFormat timeFormat = hourFormat();
timeFormat.setTimeZone(TimeZone.getDefault());
double start_hour_block = today.getTime().getTime();
double timeNow = new Date().getTime();
for(int l=0; l<=24; l++) {
if ((start_hour_block + (60000 * 60 * (l))) < timeNow) {
if((start_hour_block + (60000 * 60 * (l + 1))) >= timeNow) {
endHour = start_hour_block + (60000 * 60 * (l));
l=25;
}
}
}
for(int l=0; l<=24; l++) {
double timestamp = (endHour - (60000 * 60 * l));
xAxisValues.add(new AxisValue((long)(timestamp/fuzzer), (timeFormat.format(timestamp)).toCharArray()));
}
xAxis.setValues(xAxisValues);
xAxis.setHasLines(true);
xAxis.setTextSize(axisTextSize);
return xAxis;
}
private SimpleDateFormat hourFormat() {
return new SimpleDateFormat(DateFormat.is24HourFormat(context) ? "HH" : "h a");
}
private boolean isXLargeTablet() {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
public Axis previewXAxis(){
List<AxisValue> previewXaxisValues = new ArrayList<AxisValue>();
final java.text.DateFormat timeFormat = hourFormat();
timeFormat.setTimeZone(TimeZone.getDefault());
for(int l=0; l<=24; l+=hoursPreviewStep) {
double timestamp = (endHour - (60000 * 60 * l));
previewXaxisValues.add(new AxisValue((long)(timestamp/fuzzer), (timeFormat.format(timestamp)).toCharArray()));
}
Axis previewXaxis = new Axis();
previewXaxis.setValues(previewXaxisValues);
previewXaxis.setHasLines(true);
previewXaxis.setTextSize(previewAxisTextSize);
return previewXaxis;
}
/////////VIEWPORT RELATED//////////////
public Viewport advanceViewport(Chart chart, Chart previewChart) {
viewport = new Viewport(previewChart.getMaximumViewport());
viewport.inset((float)((86400000 / 2.5)/fuzzer), 0);
double distance_to_move = ((new Date().getTime())/fuzzer) - viewport.left - (((viewport.right - viewport.left) /2));
viewport.offset((float) distance_to_move, 0);
return viewport;
}
public double unitized(double value) {
if(doMgdl) {
return value;
} else {
return mmolConvert(value);
}
}
public String unitized_string(double value) {
DecimalFormat df = new DecimalFormat("#");
if (value >= 400) {
return "HIGH";
} else if (value >= 40) {
if(doMgdl) {
df.setMaximumFractionDigits(0);
return df.format(value);
} else {
df.setMaximumFractionDigits(1);
return df.format(mmolConvert(value));
}
} else if (value > 12) {
return "LOW";
} else {
switch((int)value) {
case 0:
return "??0";
case 1:
return "?SN";
case 2:
return "??2";
case 3:
return "?NA";
case 5:
return "?NC";
case 6:
return "?CD";
case 9:
return "?AD";
case 12:
return "?RF";
default:
return "???";
}
}
}
public String unitizedDeltaString(double value) {
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(1);
String delta_sign = "";
if (value > 0.1) { delta_sign = "+"; }
if(doMgdl) {
return delta_sign + df.format(unitized(value)) + " mg/dl";
} else {
return delta_sign + df.format(unitized(value)) + " mmol";
}
}
public double mmolConvert(double mgdl) {
return mgdl * Constants.MGDL_TO_MMOLL;
}
public String unit() {
if(doMgdl){
return "mg/dl";
} else {
return "mmol";
}
}
}