/*
 * histogram.c
 *
 *  Created on: Jan 1, 2015
 *      Author: hutch
 */

#include "histogram.h"
#include "supportFiles/display.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "supportFiles/utils.h"


static uint16_t histogram_barWidth;		// May share this other functions in this package.
static histogram_data_t histogram_bar_data[HISTOGRAM_BAR_COUNT];			// Current histogram data.
static histogram_data_t histogram_bar_old_data[HISTOGRAM_BAR_COUNT];	// Keep the old stuff around so you can erase things properly.
static bool initFlag = false;	// Keep track whether histogram_init() has been called.
// These are the default colors for the bars.
static uint16_t histogram_barColors[HISTOGRAM_MAX_BAR_COUNT] = {DISPLAY_BLUE, DISPLAY_RED, DISPLAY_GREEN, DISPLAY_CYAN, DISPLAY_MAGENTA,
																																DISPLAY_YELLOW, DISPLAY_WHITE, DISPLAY_BLUE, DISPLAY_RED, DISPLAY_GREEN};
// Default labels for the histogram bars.
static char histogram_label[HISTOGRAM_MAX_BAR_COUNT][HISTOGRAM_MAX_BAR_LABEL_WIDTH] = {{"0"}, {"1"}, {"2"},{"3"}, {"4"}, {"5"}, {"6"}, {"7"}, {"8"}, {"9"}};

void histogram_drawLabels() {
	uint16_t labelOffset = (histogram_barWidth - (CHAR_WIDTH * TEXT_SIZE))/2;
	display_setTextSize(TEXT_SIZE);
	for (int i=0; i<HISTOGRAM_BAR_COUNT; i++) {
		display_setCursor(i*(histogram_barWidth+HISTOGRAM_BAR_X_GAP) + labelOffset, display_height()-(CHAR_HEIGHT * TEXT_SIZE)+2);
		display_setTextColor(histogram_barColors[i]);
		display_print(histogram_label[i]);
	}
}

void histogram_init() {
	if (HISTOGRAM_BAR_COUNT > HISTOGRAM_MAX_BAR_COUNT) {
		printf("Error: histogram_init(): HISTOGRAM_BAR_COUNT (%d) is larger than the max allowed (%d)", HISTOGRAM_BAR_COUNT, HISTOGRAM_MAX_BAR_COUNT);
		exit(0);
	}
	if (initFlag) return;					// If already called, do nothing.
	display_init();								// Init the display package.
	histogram_barWidth = (display_width() / HISTOGRAM_BAR_COUNT) - HISTOGRAM_BAR_X_GAP;
	for (int i=0; i<HISTOGRAM_BAR_COUNT; i++) {
		histogram_bar_data[i] = 0;
		histogram_bar_old_data[i] = 0;
	}
	display_fillScreen(DISPLAY_BLACK);
	histogram_drawLabels();
	initFlag = true;
}


void histogram_setBarData(histogram_index_t barIndex, histogram_data_t data) {
	if (!initFlag) {
		printf("Error! histogram_setBarData(): must call histogram_init() before calling this function.\n\r");
		return;
	}
	// Error checking.
	if (barIndex > HISTOGRAM_BAR_COUNT) {
		printf("Error! histogram_setBarData(): barIndex(%d) is greater than maximum (%d)\n\r", barIndex, HISTOGRAM_BAR_COUNT-1);
		return;
	}
	// Error checking.
	if (data > HISTOGRAM_MAX_BAR_DATA_IN_PIXELS) {
		printf("Error! histogram_setBarData(): data (%d) is greater than maximum (%d) for index(%d) \n\r", data, HISTOGRAM_MAX_BAR_DATA_IN_PIXELS-1, barIndex);
		return;
	}
	// update the data in the array but don't render anything on the display.
	if (data != histogram_bar_data[barIndex]) {						// Only modify the data if it has changed.
		histogram_bar_old_data[barIndex] = histogram_bar_data[barIndex];	// Save the old data so you render things properly.
		histogram_bar_data[barIndex] = data;								// Store the data because it changed.
	}
}

// display_fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
// This updates the display.
void histogram_updateDisplay() {
	if (!initFlag) {
		printf("Error! histogram_displayUpdate(): must call histogram_init() before calling this function.\n\r");
		return;
	}
	for (int i=0; i<HISTOGRAM_BAR_COUNT; i++) {
		histogram_data_t oldData = histogram_bar_old_data[i];
		histogram_data_t data = histogram_bar_data[i];
		if (oldData != data) {
			display_fillRect(i*(histogram_barWidth+HISTOGRAM_BAR_X_GAP), display_height() - oldData - HISTOGRAM_BAR_Y_GAP,
													histogram_barWidth, oldData, DISPLAY_BLACK);			// Erase the previous bar.
			display_fillRect(i*(histogram_barWidth+HISTOGRAM_BAR_X_GAP), display_height() - data - HISTOGRAM_BAR_Y_GAP,
													histogram_barWidth, data, histogram_barColors[i]);// Draw the new bar.
			histogram_bar_old_data[i] = histogram_bar_data[i];	// Old data and new data are the same after the update.
		}
	}
}

// Runs a short test that writes random values to the histogram bar-values as
// specified by the #defines below.
#define HISTOGRAM_RUN_TEST_ITERATION_COUNT 10
#define HISTOGRAM_RUN_TEST_LOOP_DELAY_MS 500
void histogram_runTest() {
	histogram_init();	// Must init the histogram data structures.
	for (int i=0; i<HISTOGRAM_RUN_TEST_ITERATION_COUNT; i++) {	// Loop as required.
		for (int j=0; j<HISTOGRAM_BAR_COUNT; j++) {								// set each of the bar values.
			histogram_setBarData(j, rand() % HISTOGRAM_MAX_BAR_DATA_IN_PIXELS);	// set the bar data to a random value.
		}
		histogram_updateDisplay();	// update the display.
		utils_msDelay(HISTOGRAM_RUN_TEST_LOOP_DELAY_MS);	// Slow the update so you can see it happen.
	}
}



