#include <rtos.h>
#include <net.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <graph.h>
#include <httpd.h>
#include <math.h>
#include <strlst.h>
#include <stdlib.h>

/*
 *
 */
int maxvalue = 10;

int newdata( void )
{
    int y;
    static int pos = 0;
    int period = 10;

    y = (int)((long)maxvalue * pos++)/period;
    if ( pos > period ) pos = 0;
    return( y );
}

/*-----------------------------------------------------------------------*
 * 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 POINTS 20
static int last_n_points[ POINTS ];    /* this is the series over time */
int curhits;                    /* this is the value in this period */
crit_x *collector_cs = NULL;

void collector( DWORD param )
{
    int i;

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

    /* clear counter */
    curhits = 0;

    /* 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 ( i = 0 ; i < POINTS - 2 ; ++i )
            last_n_points[ i ] = last_n_points[ i + 1 ];
        /* and include the most recent */
        last_n_points[ POINTS - 2 ] = curhits;

        /* and reset the input to 0 for next round */
        curhits = 0;


        /* now add some data */
        curhits = newdata();

        cs_exit( collector_cs );

    } while ( 1 );
}


/* graph code */
crit_x *graph_cs = NULL;
void web_graph( tcp_Socket *s )
{
    graph_x *g;

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

    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 , "Some Time Function", GRWIDTH/5, GRHEIGHT - 10, 0 );

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

        last_n_points[ POINTS - 1 ] = curhits;

        gr_linegraph( g, POINTS, last_n_points, NULL, "now", 0, 1 );

        /* we don't need the lock on the data anymore */
        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 );
    }
    cs_exit( graph_cs );
}

/*-----------------------------------------------------------------------*
 * Change Parameters of the scope                                        *
 *-----------------------------------------------------------------------*/

void web_setparms( tcp_Socket *s )
{
    stringlist *sl;
    char *p, *q;
    char buf[ 64 ];

    sl = cgi_getstrings( s );

    if ( (p = strlst_findfirst( sl, "NUMBER", NULL, &q )) != NULL )
        maxvalue = atoi( q );

    cgi_freestrings( sl );

    html_hdr(s,"Parameters");

    sock_puts( s, "<p>Changes made on this screen will affect the"
                  "graph appearing in the frame on the right</p>");
    sock_puts( s, "<form method=\"post\" action=\"setparms\">"
                  "Amplitude "
                  "<input type=\"TEXT\" name=\"NUMBER\" value=\"");
    itoa( maxvalue, buf, 10 );
    sock_puts( s, buf );
    sock_puts( s, "\">"
                  "<input type=\"submit\" value=\"Submit\">"
                  "<input type=\"reset\"  value=\"Reset\">"
                  "</form>");
    html_tail( s );
}

/***********************************************************************
 * - 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 );
        } else
            http_dump( s, "web", file,ext );
    } else {
        /* non gif stuff */
        sock_puts( s, "Content-Type: text/html\r\n");
        if ( !strcmp( file, "/setparms" ))
            web_setparms( s );
        else if ( !stricmp( file, "/" ))
            http_dump( s, "web", "index","htm" );
        else
            http_dump( s, "web", file, ext );
    }
}

