/** 
 * @author Rémi Heredero (remi@heredero.ch)
 * @version 1.0.0
 * @date 2023-06-15
 */

#include "app.h"
#include "factory/factory.h"
#include "../middleware/blinker.h"
#include "../middleware/clickHandler.h"

void clickL(APP* me){
    POST(me, &APP_processEvent, evAPclickL, 0, 0);
}
void clickLn(APP* me){
    POST(me, &APP_processEvent, evAPclickLn, 0, 0);
}
void clickR(APP* me){
    POST(me, &APP_processEvent, evAPclickR, 0, 0);
}
void clickRn(APP* me){
    POST(me, &APP_processEvent, evAPclickRn, 0, 0);
}
void endL(APP* me){
    POST(me, &APP_processEvent, evAPendL, 0, 0);
}
void endR(APP* me){
    POST(me, &APP_processEvent, evAPendR, 0, 0);
}
void longClick(APP* me){
    POST(me, &APP_processEvent, evAPlongClick, 0, 0);
}



void APP_init(APP* me){
    
    me->state = STAP_INIT;
    
    CLICK_HANDLER_setSingleClickCallback(ch1(), CLICK_HANDLER_defineCallBack(&clickL, me));
    CLICK_HANDLER_setSingleClickCallback(ch3(), CLICK_HANDLER_defineCallBack(&clickR, me));
    
    CLICK_HANDLER_setDoubleClickCallback(ch1(), CLICK_HANDLER_defineCallBack(&clickLn, me));
    CLICK_HANDLER_setDoubleClickCallback(ch3(), CLICK_HANDLER_defineCallBack(&clickRn, me));
    
    CLICK_HANDLER_setLongClickCallback(ch1(), CLICK_HANDLER_defineCallBack(&longClick, me));
    CLICK_HANDLER_setLongClickCallback(ch3(), CLICK_HANDLER_defineCallBack(&longClick, me));
    
    BLINKER_setFinished(blL(), BLINKER_defineCallBack(&endL, me));
    BLINKER_setFinished(blR(), BLINKER_defineCallBack(&endR, me));
    
}

void APP_startBehaviour(APP* me){
    POST(me, &APP_processEvent, evAPinit, 0, 0);
}

bool APP_processEvent(Event* ev){
    bool processed = false;
    APP* me = (APP*) Event_getTarget(ev);
    APP_STATES oldState = me->state;
    evIDT evid = Event_getId(ev);
    
    switch(me->state) { // In state
        case STAP_INIT:
            if(evid == evAPinit) {
                me->state = STAP_WAIT;
            }
            break;
            
        case STAP_WAIT:
            if(evid == evAPclickL) {
                me->state = STAP_BLINKER_L;
                BLINKER_blink(blL());
            }
            if(evid == evAPclickLn) {
                me->state = STAP_BLINKER_L;
                BLINKER_blinkN(blL());
            }
            if(evid == evAPclickR) {
                me->state = STAP_BLINKER_R;
                BLINKER_blink(blR());
            }
            if(evid == evAPclickRn) {
                me->state = STAP_BLINKER_R;
                BLINKER_blinkN(blR());
            }
            if(evid == evAPlongClick) {
                me->state = STAP_BLINKER_W;
                BLINKER_blink(blB());
            }
            break;
            
        case STAP_BLINKER_L:
            if(evid == evAPclickR){
                me->state = STAP_BLINKER_LR;
                BLINKER_blink(blR());
            }
            if(evid == evAPclickRn){
                me->state = STAP_BLINKER_LR;
                BLINKER_blinkN(blR());
            }
            if(evid == evAPclickL) {
                me->state = STAP_WAIT;
                BLINKER_endBlink(blL());
            }
            if(evid == evAPendL) {
                me->state = STAP_WAIT;
            }
            if(evid == evAPlongClick) {
                me->state = STAP_BLINKER_W;
                BLINKER_endBlink(blL());
                BLINKER_blink(blB());
            }
            break;
            
        case STAP_BLINKER_R:
            if(evid == evAPclickL){
                me->state = STAP_BLINKER_LR;
                BLINKER_blink(blL());
            }
            if(evid == evAPclickLn){
                me->state = STAP_BLINKER_LR;
                BLINKER_blinkN(blL());
            }
            if(evid == evAPclickR) {
                me->state = STAP_WAIT;
                BLINKER_endBlink(blR());
            }
            if(evid == evAPendR) {
                me->state = STAP_WAIT;
            }
            if(evid == evAPlongClick) {
                me->state = STAP_BLINKER_W;
                BLINKER_endBlink(blR());
                BLINKER_blink(blB());
            }
            break;
            
        case STAP_BLINKER_LR:
            if(evid == evAPclickR) {
                me->state = STAP_BLINKER_L;
                BLINKER_endBlink(blR());
            }
            if(evid == evAPendR) {
                me->state = STAP_BLINKER_L;
            }
            if(evid == evAPclickL) {
                me->state = STAP_BLINKER_R;
                BLINKER_endBlink(blL());
            }
            if(evid == evAPendL) {
                me->state = STAP_BLINKER_R;
            }
            if(evid == evAPlongClick) {
                me->state = STAP_BLINKER_W;
                BLINKER_endBlink(blL());
                BLINKER_endBlink(blR());
                BLINKER_blink(blB());
            }
            break;
            
        case STAP_BLINKER_W:
            if(evid == evAPlongClick){
                me->state = STAP_WAIT;
                BLINKER_endBlink(blB());
            }
            break;
            
    }
    
    if(oldState != me->state) {
        switch(oldState) { // on exit
            case STAP_INIT:
                break;
                
            case STAP_WAIT:
                break;
                
            case STAP_BLINKER_L:
                break;
                
            case STAP_BLINKER_R:
                break;
                
            case STAP_BLINKER_LR:
                break;
                
            case STAP_BLINKER_W:
                break;
        }
        
        switch(me->state) { // on entry
            case STAP_INIT:
                break;
                
            case STAP_WAIT:
                break;
                
            case STAP_BLINKER_L:
                break;
                
            case STAP_BLINKER_R:
                break;
                
            case STAP_BLINKER_LR:
                break;
                
            case STAP_BLINKER_W:
                break;
                
        }
        processed = true;
    }
    return processed;
}
