/*
 * fbdash.c
 *
 * Adapted by Florian Klemenz for use in the fb_dash project
 *
 * Credit for most of the framebuffer-related source code goes to 
 * http://raspberrycompote.blogspot.com/
 * Thanks for providing an excellent tutorial!

 * -------------------------------------------------------------------------------------------- 
 *
 * http://raspberrycompote.blogspot.ie/2014/03/low-level-graphics-on-raspberry-pi-part_14.html
 *
 * Original work by J-P Rosti (a.k.a -rst- and 'Raspberry Compote')
 *
 * Licensed under the Creative Commons Attribution 3.0 Unported License
 * (http://creativecommons.org/licenses/by/3.0/deed.en_US)
 *
 * Distributed in the hope that this will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 */


#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <float.h>

#include "fblib.h"
#include "fbdata.h"

#define DEVICE "/dev/fb1"
#define WIDTH 240
#define HEIGHT 320
#define BITS_PER_PIXEL 16


void updateSlot(screen fb, sourcedata data, int x_offset, int y_offset, color c) {
	render_string(fb, ubuntu_mono_24, data.text, x_offset, y_offset, c.r, c.g, c.b);
	
	if (data.temperature) render_string(fb, ubuntu_mono_48, data.temperature, x_offset + 115, y_offset - 9, c.r, c.g, c.b);
	render_string(fb, ubuntu_mono_48, "C", x_offset + 195, y_offset - 9, c.r, c.g, c.b);
	
	if (data.humidity) render_string(fb, ubuntu_mono_48, data.humidity, x_offset + 115, y_offset + 26, c.r, c.g, c.b);
	render_string(fb, ubuntu_mono_48, "%", x_offset + 195, y_offset + 26, c.r, c.g, c.b);
}

void draw(screen fb) {
    clear_screen(fb);
    
	int slot_height = fb.height / 4;

    // horizontal spacersint x_space = 10;
    for (int i = 1; i < 4; i++) {
        int x0 = 15;
        int x1 = fb.width - x0;
        int y = slot_height * i;

        int r = 225;
        int g = 32;
        int b = 32;
        
        draw_line(fb, x0, y-1, x1, y-1, r, g, b);
        draw_line(fb, x0, y  , x1, y  , r, g, b);
        draw_line(fb, x0, y+1, x1, y+1, r, g, b);
    }

    
	// define what to display
    sourcedata data[4] = {
		// text				| temperature | humidity
	    { "Esszimmer"       , NULL, NULL },
    	{ "Wohnzimmer"      , NULL, NULL },
        { "Schlafzimmer"    , NULL, NULL },
        { "Abstellkammer"   , NULL, NULL }
    };

    // fetch data from database and update screen 
	printf("Fetching data...\n");
	updateData(data);

	// update dashboard    
	printf("Updating dashboard...\n");
    for (int i = 0; i < 4; i++) {
        color c = {255,125 + 25*i,25 + 25*i};
        updateSlot(fb, data[i], 15, 7 + slot_height * i, c);

		// release allocated memory for values
        free(data[i].temperature);
        free(data[i].humidity);
    }
}


// application entry point
int main(int argc, char* argv[]) {
	char *fbp = 0;
    int fbfd = 0;
    long int screensize = 0;

    // Open the framebuffer file for reading and writing
    fbfd = open(DEVICE, O_RDWR);
    if (fbfd == -1) {
        printf("Error: cannot open framebuffer device.\n");
        return(1);
    }
    printf("The framebuffer device was opened successfully.\n");

    // map fb to user mem 
    screensize = WIDTH * HEIGHT * (BITS_PER_PIXEL / 8);
    fbp = (char*)mmap(0, 
              screensize, 
              PROT_READ | PROT_WRITE, 
              MAP_SHARED, 
              fbfd, 
              0);


    if ((int)fbp == -1) {
        printf("Failed to mmap.\n");
    }
    else {
		// define the screen object
		screen fb = {
			.buffer = fbp,
			.width  = WIDTH,
			.height = HEIGHT,
			.bpp = BITS_PER_PIXEL,
			.step = (BITS_PER_PIXEL / 8),
			.line = (BITS_PER_PIXEL / 8) * WIDTH,
			.screensize = screensize,
		}; 
        
        // draw...
		draw(fb);
    }

    // cleanup
    //clear_screen(fbp);
    munmap(fbp, screensize);
    close(fbfd);

    return 0;
}
