#include <rtos.h>
#include <net.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <graph.h>
#include <httpd.h>
#include <emath.h>
#include <strlst.h>
#include <stdlib.h>
#include "ldriver.h"

/*-----------------------------------------------------------------------*
/* Read A/D - returns the temperature in Celcius times 10                *
 *-----------------------------------------------------------------------*/
int GetTemperatureX10( WORD sensor )
{
    PutA2DChannel( sensor );
    return (GetA2D() - 2732);
}

/*-----------------------------------------------------------------------*
 * Sample Data Collector                                                 *
 *                                                                       *
 * This code is mostly in charge of aging the data history               *
 * every 5 seconds.                                                      *
 *                                                                       *
 * It is placed in a separate thread so it is easy to read               *
 *-----------------------------------------------------------------------*/

#define SOURCES 2   /* two data sources, 0 and 1 */
#define POINTS 40
static int last_n_points[ SOURCES ][ POINTS ];    /* this is the series over time */
crit_x *collector_cs = NULL;

void collector( DWORD param )
{
    int i,j;
    int celcius;

    /* clear history */
    memset( last_n_points, 0, sizeof( last_n_points ));

    /* we will use a critical section so that collector and
     * reporter are not interrupting each other
     */
    collector_cs = cs_alloc();

    do {
        rt_sleep( 1000 );    /* sample every second */
        /* react to that collected data
         * start by locking it
         */
        cs_enter( collector_cs );

        /* remove the last one from history */
        for ( j = 0 ; j < SOURCES ; ++j ) {
            for ( i = 0 ; i < POINTS - 1 ; ++i )
                last_n_points[ j ][ i ] = last_n_points[ j ][ i + 1 ];
        }
        /* now add some new data */
        for ( j = 0 ; j < SOURCES ; ++j ) {
            last_n_points[ j ][ POINTS - 1 ] = GetTemperatureX10( j );
        }
        cs_exit( collector_cs );

    } while ( 1 );
}


/* graph code */
crit_x *graph_cs = NULL;

void web_graph( tcp_Socket *s, WORD table )
{
    graph_x *g;


    kblock();
    if ( graph_cs == NULL )
        graph_cs = cs_alloc();
    kunblock();

    if ( table > SOURCES )  table = 0;   /* or else we can point to garbage */

    cs_enter( graph_cs );

#define GRWIDTH 200
#define GRHEIGHT 50
    g = gr_alloc( GRWIDTH, GRHEIGHT);
    if ( g != NULL ) {
        gr_background( g, 7 );

        /* put a title on the graph */
        gr_text_at( g , "Celcius X 10", GRWIDTH/5, GRHEIGHT - 10, 0 );

        /* we need to lock the data for this time */
        cs_enter( collector_cs );

        gr_linegraph( g, POINTS, last_n_points[table], NULL, NULL, 0, 1 );

        /* we don't need the lock on the data anymore */
        cs_exit( graph_cs );
        cs_exit( collector_cs );

        sock_mode( s, TCP_MODE_BINARY );
        sock_mode( s, TCP_MODE_BINARY | TCP_MODE_NONAGLE );
        gr_gif( s, g );     /* write the graph out as a GIF file */
        gr_free( g );
        return;
    }
    cs_exit( graph_cs );
}


void ShowTemperature( tcp_Socket *s, int sensor )
{
    int value;
    int f;
    char buffer[128];


    value = last_n_points[ sensor ][ POINTS - 1];
    f =  9*value/5 + 320;

    sprintf( buffer, " %u.%u C,  %u.%u F ",
            value / 10, value % 10,
            f / 10, f % 10);
    sock_puts( s, buffer );
}

void ShowProbe0( tcp_Socket *s, stringlist *cookies )
{
    ShowTemperature( s, 0 );
}
void ShowProbe1( tcp_Socket *s, stringlist *cookies )
{
    ShowTemperature( s, 1 );
}

static ssi_type ssi_list[] =
  { { "probe0", ShowProbe0 },
    { "probe1", ShowProbe1 },
    NULL };

/***********************************************************************
 * - the web server calls this proc for each web request               *
 * - it is called in the context of *one* of the HTTPD threads,        *
 *   though which is not known or important                            *
 * - multiple threads may be in the same proc at the same time         *
 ***********************************************************************/
void user_proc( tcp_Socket *s, char *cmd, char *file, char *ext,
    stringlist *cookies )
{
    char *p, *q;

    /* prepare output */
    if ( !stricmp( ext, "gif"))  {
        if ( !strnicmp( file, "/graph", 6 )) {
            /* short expiry (1 sec) so it re-loads */
            html_datestring( s, "Expires: content=\"%s\"", 1);
            sock_puts( s, "Content-Type: image/gif\r\n");

            web_graph( s, file[6] - '0' );  /* index to table */
        } else
            http_dump( s, "web", file,ext );
    } else {
        /* non gif stuff */
        sock_puts( s, "Content-Type: text/html\r\n");
        if ( !stricmp( file, "/" ))
            http_shtml( s, "web", "index","sht", ssi_list, cookies );
        else if ( !stricmp( ext, "sht" ))
            http_shtml( s, "web", file, ext, ssi_list, cookies );
        else
            http_dump( s, "web", file, ext );
    }
}

