#include "mbed.h"
#include "vt100.h"
#include "edge_mgr.h"
#include "edge_reset_mgr.h"
#include "edge_time.h"
#include "edge_sensor.h"

extern vt100 *tty ;
static uint16_t id = 0 ;

edge_sensor::edge_sensor()
{
    _interval = 0 ;
    _prev_status = EDGE_SENSOR_INACTIVE ;
    _status = EDGE_SENSOR_INACTIVE ;
    _id = id++ ;
    _enable = false ;
    _error_count = 0 ;
    _sample_error = 0 ;
}

edge_sensor::~edge_sensor()
{
}

void edge_sensor::reset(void)
{
    _status = EDGE_SENSOR_INACTIVE ;
}

void edge_sensor::enable(void) 
{
    _enable = true ;
}

void edge_sensor::disable(void) 
{
    _enable = false ;
}

bool edge_sensor::isEnabled(void)
{
    return( _enable ) ;
}

void edge_sensor::prepare(void)
{
//    printf("Sensor %d prepare for sample\n", _id) ;
}

int edge_sensor::sample(void)
{
    int result = EDGE_SAMPLE_SUCCESS ;
//    printf("Sensor %d sample\n", _id) ;
    return( result ) ;
}

int edge_sensor::deliver(void) 
{
//  printf("Sensor %d data delivered\n", _id) ;
    /* usually return( result == afSUCCESS ) ; */
    return 1 ; /* return non zero for success */
}

void edge_sensor::show(void)
{
    /* display value(s) to TFT */
}

void edge_sensor::displayTime(int32_t ts)
{
    struct tm timestruct ;
    if (display) {
reset_watch_dog() ;
        ts2tm(ts, &timestruct) ;
reset_watch_dog() ;
        display->set_font((unsigned char*) Arial12x12);
        display->set_font_zoom(2, 2) ;
        display->foreground(White) ;
//        display->locate(10, 5) ;
        display->printf("%d/%02d/%02d %02d:%02d:%02d",
            timestruct.tm_year,
            timestruct.tm_mon + 1,
            timestruct.tm_mday,
            timestruct.tm_hour,
            timestruct.tm_min,
            timestruct.tm_sec
        ) ;
reset_watch_dog() ;
    }
}

void edge_sensor::toJson(char *buf)
{
    sprintf(buf, "EDGE_SENSOR%d is not a real sensor", _id) ;
}

void edge_sensor::setInterval(uint16_t interval) 
{
    _interval = interval ;
}

uint16_t edge_sensor::getInterval(void) 
{
    return( _interval ) ;
}

int edge_sensor::getStatus(void)
{
    return( _status ) ;
}

/*
#define EDGE_SENSOR_INACTIVE    0
#define EDGE_SENSOR_WAIT        1
#define EDGE_SENSOR_READY       2
#define EDGE_SENSOR_PREPARED    3
#define EDGE_SENSOR_SAMPLED     4
#define EDGE_SENSOR_DELIVERD    5
*/

int edge_sensor::runStateMachine(void)
{
    int result ;
    reset_watch_dog() ;
    switch(_status) {
    case EDGE_SENSOR_INACTIVE: /* inactive */
        if (isEnabled()) {
            _status = EDGE_SENSOR_WAIT ;
        }
        _prev_status = EDGE_SENSOR_INACTIVE ;
        break ;
    case EDGE_SENSOR_WAIT: /* wait for interval time expires */
        if (_prev_status == EDGE_SENSOR_INACTIVE) { // initial end_interval
            _end_interval = edge_time + _interval ;
        }
        _prev_status = EDGE_SENSOR_WAIT ;
        if (edge_time >= _end_interval) {
            _status = EDGE_SENSOR_READY ;
            _end_interval += _interval ;
        }
        break ;
    case EDGE_SENSOR_READY: /* prepare to sample */
        result = sample() ;
        if (result == EDGE_SAMPLE_SUCCESS) {
            _status = EDGE_SENSOR_SAMPLED ;
            _sample_error = 0 ;
        } else {
            reset_watch_dog() ;
            printf("Sampling error: ") ;
            switch(_id) {
            case SENSOR_ID_ACCEL:  printf("Accel (MMA8451Q) ") ;  break ;
            case SENSOR_ID_COLOR1: printf("Color1 (VEML6040) ") ; break ;
            case SENSOR_ID_COLOR2: printf("Color2 (VEML6040) ") ; break ;
            case SENSOR_ID_TEMP: printf("Temp (LM75B) ") ;      break ;
            case SENSOR_ID_PRESS: printf("Pressure (PSE530) ") ; break ;
            default: printf("Sensor[%d] ", _id) ;  break ;
            }
            switch(result) {
            case -2: printf("Bus Busy") ;         break ;
            case -1: printf("No Slave") ;         break ;
            case 0: printf("No Error") ;          break ;
            case 1: printf("Nack Received") ;     break ;
            case 2: printf("Time Out") ;          break ;
            default: printf("error[%d]",result) ; break ;
            }
            _sample_error++ ;
            printf("\n") ;
        }
        if (_sample_error > SAMPLE_ERROR_TOLERANCE) {
            printf("Sampling error of sensor[%d]\n", _id) ;
            wait(0.1) ;
            reset_watch_dog() ;
            reboot_edge() ;
        }
        _prev_status = EDGE_SENSOR_READY ;
        break ;
    case EDGE_SENSOR_SAMPLED: /* data is ready, wait for delivery */
        if (_prev_status != EDGE_SENSOR_SAMPLED) {
            _error_count = 0 ;
        }
        result = deliver() ;
        if (result) {
            _status = EDGE_SENSOR_DELIVERED ; // EDGE_SENSOR_INACTIVE ;
        } else {
            _error_count++ ;
        }

        _prev_status = EDGE_SENSOR_SAMPLED ;
        break ;
    case EDGE_SENSOR_DELIVERED:
        show() ;
        _status = EDGE_SENSOR_WAIT ;
        _prev_status = EDGE_SENSOR_DELIVERED ;
        break ;
    }
    reset_watch_dog() ;
    return(_status) ;
}
    
