package com.google.araplox;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import android.app.Activity;
import android.graphics.Color;
import android.graphics.Paint.Align;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Window;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.google.araplox.AFE4400Thread;

public class AraPloxActivity extends Activity {
	private static final String TAG = "AraPlox/Activity";

	private static TextView bpmTextView;
	private static Handler mHandler = null;
	private static AFE4400Thread afe4400Thread = null;
	private GraphicalView chart_view = null;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.d(TAG, "onCreate()");
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_ara_plox);
		bpmTextView = (TextView)findViewById(R.id.textView);

		mHandler = new Handler() {
			public void handleMessage(Message msg) {
				handleAFE4400Message(msg);
			}
		};
	}

	private String[] fakeBPMs = new String[] {
			"72", "72", "74", "75", "73", "73", "70", "70", "71", "73", "76", "78"
	};
	private int fakeBPMCount = 0;
	private void handleAFE4400Message(Message msg) {
		//	Log.d(TAG, "Message received: arg1: " + msg.arg1 + " arg2: " + msg.arg2);
		double x = msg.arg1;
		double y = msg.arg2;

		xySeries.add(x, y);
		// Scroll continuously after ~150 points
		if (x > 150) {
			xySeries.remove(0);
		}

		// Autoscale
		double maxX = xySeries.getMaxX();
		double minX = xySeries.getMinX();
		double maxY = xySeries.getMaxY();
		double minY = xySeries.getMinY();
		renderer.setXAxisMax(maxX);
		renderer.setXAxisMin(minX);
		renderer.setYAxisMax(maxY);
		renderer.setYAxisMin(minY);

		chart_view.repaint();
		
		// fake pulse rate...
		if (x % 10 == 0) {
			bpmTextView.setText(fakeBPMs[fakeBPMCount++] + " bpm");
			if (fakeBPMCount == fakeBPMs.length) {
				fakeBPMCount = 0;
			}
		}
	}

	private XYMultipleSeriesRenderer renderer;
	private XYMultipleSeriesDataset dataSet;
	private XYSeries xySeries;

	private void makeChart() {
		dataSet = new XYMultipleSeriesDataset();
		xySeries = new XYSeries("");
		dataSet.addSeries(xySeries);

		int[] colors = new int[] {Color.RED};
		PointStyle[] styles = new PointStyle[] {PointStyle.CIRCLE};

		renderer = new XYMultipleSeriesRenderer();
		
		int length = colors.length;
		for (int i = 0; i < length; i++) {
			XYSeriesRenderer r = new XYSeriesRenderer();
			r.setFillPoints(true);
			r.setLineWidth(10.0f);
			r.setPointStrokeWidth(1);
			r.setColor(colors[i]);
			r.setPointStyle(styles[i]);
			renderer.addSeriesRenderer(r);
		}

		renderer.setChartTitleTextSize(20);
		renderer.setLabelsTextSize(15);
		renderer.setLegendTextSize(15);
		renderer.setPointSize(5f);
		renderer.setMargins(new int[] { 100, 100, 100, 100 });
		renderer.setXAxisMin(0);
		renderer.setXAxisMax(10);
		renderer.setYAxisMin(0);
		renderer.setYAxisMax(100);
		renderer.setAxesColor(Color.BLACK);
		renderer.setLabelsColor(Color.BLACK);
		renderer.setShowLegend(false);
		renderer.setXLabels(10);
		renderer.setYLabels(0);
		renderer.setShowGrid(false);
		renderer.setXLabelsAlign(Align.CENTER);
		renderer.setApplyBackgroundColor(true);
		renderer.setBackgroundColor(Color.WHITE);
		renderer.setMarginsColor(Color.WHITE);
		if (chart_view == null) {
			LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
			chart_view = ChartFactory.getCubeLineChartView(this, dataSet, renderer, 1.0f);
			layout.addView(chart_view, new LayoutParams(LayoutParams.FILL_PARENT,
					LayoutParams.FILL_PARENT));
			chart_view.repaint();
		}
	}


	protected void onResume() {
		super.onResume();
		Log.d(TAG, "onResume()");
		if (afe4400Thread == null) {
			afe4400Thread = new AFE4400Thread(getApplicationContext(), mHandler);
			afe4400Thread.start();
		}
		makeChart();
	}

	protected void onPause() {
		super.onPause();
		Log.d(TAG, "onPause()");
		if (afe4400Thread != null) {
			afe4400Thread.requestStop();
			afe4400Thread = null;
		}

	}
	
	protected void onStop() {
		super.onStop();
		Log.d(TAG, "onStop()");
		if (chart_view != null) {
			LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
			layout.removeView(chart_view);
			chart_view = null;
		}
	}
}
