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

#include "clickHandler.h"

void CLICK_HANDLER_BUTTON_PRESS(CLICK_HANDLER* me){
    POST(me, &CLICK_HANDLER_processEvent, evCHpbPress, 0, 0);
}

void CLICK_HANDLER_BUTTON_RELEASE(CLICK_HANDLER * me) {
    POST(me, &CLICK_HANDLER_processEvent, evCHpbRelease, 0, 0);
}

void CLICK_HANDLER_init(CLICK_HANDLER* me, BUTTON* b){
    me->button = b;
    me->state = STCH_INIT;
    me->longClick.fCallBack = NULL;
    me->singleClick.fCallBack = NULL;
    me->doubleClick.fCallBack = NULL;
    
    buttonCallBack pbPressCallBack;
    pbPressCallBack.fCallBack = CLICK_HANDLER_BUTTON_PRESS;
    pbPressCallBack.param = me;
    
    buttonCallBack pbReleaseCallBack;
    pbReleaseCallBack.fCallBack = CLICK_HANDLER_BUTTON_RELEASE;
    pbReleaseCallBack.param = me;
    
    BUTTON_setEventFunctions(b, pbPressCallBack, pbReleaseCallBack);
}

void CLICK_HANDLER_startBehaviour(CLICK_HANDLER* me){
    POST(me, &CLICK_HANDLER_processEvent, evCHinit, 0, 0);
}

clickHandlerCallBack CLICK_HANDLER_defineCallBack(fClickHandlerCallBack f, void* param) {
    clickHandlerCallBack c;
    c.fCallBack = f;
    c.param = param;
    return c;
}

void CLICK_HANDLER_setLongClickCallback(CLICK_HANDLER* me, clickHandlerCallBack callBack) {
    me->longClick = callBack;
}

void CLICK_HANDLER_setSingleClickCallback(CLICK_HANDLER* me, clickHandlerCallBack callBack) {
    me->singleClick = callBack;
}

void CLICK_HANDLER_setDoubleClickCallback(CLICK_HANDLER* me, clickHandlerCallBack callBack) {
    me->doubleClick = callBack;
}

bool CLICK_HANDLER_processEvent(Event* ev) {
    bool processed = false; 
    CLICK_HANDLER* me = (CLICK_HANDLER*)Event_getTarget(ev);
    CLICK_HANDLER_STATES oldState = me->state;
    evIDT evid = Event_getId(ev);
    
    switch(me->state) {
        case STCH_INIT:
            if(evid == evCHinit) {
                me->state = STCH_WAIT;
            }
            break;
            
        case STCH_WAIT:
            
            if(evid == evCHpbPress) {
                me->state = STCH_LONG_CLICK;
                POST(me, &CLICK_HANDLER_processEvent, evCHtimer, CH_CLICK_TIMER, 0);
            }
            
            break;
            
            
        case STCH_LONG_CLICK: 
            
            if(evid == evCHpbRelease) {
                me->state = STCH_SINGLE_CLICK;
            }
            
            if(evid == evCHtimer) {
                me->state = STCH_WAIT;
                if(me->longClick.fCallBack != NULL) {
                    me->longClick.fCallBack(me->longClick.param);
                }
            }
            
            break;
            
            
        case STCH_SINGLE_CLICK:
            
            if(evid == evCHpbPress) {
                me->state = STCH_DOUBLE_CLICK;
            }
            
            if(evid == evCHtimer) {
                me->state = STCH_WAIT;
                if(me->singleClick.fCallBack != NULL) {
                    me->singleClick.fCallBack(me->singleClick.param);
                }
            }
            
            break;
            
            
        case STCH_DOUBLE_CLICK:
            
            if(evid == evCHpbRelease){
                me->state = STCH_WAIT;
                if(me->doubleClick.fCallBack != NULL){
                    me->doubleClick.fCallBack(me->doubleClick.param);
                }
            }
            
            if(evid == evCHtimer) {
                me->state = STCH_WAIT;
                if(me->doubleClick.fCallBack != NULL) {
                    me->doubleClick.fCallBack(me->doubleClick.param);
                }
            }
            
            break;
            
    }
    
    if(oldState != me->state) {
        switch(oldState) {
            case STCH_INIT: 
                break;
                
            case STCH_WAIT:
                break;
                
            case STCH_LONG_CLICK:
                break;
                
            case STCH_SINGLE_CLICK:
                break;
                
            case STCH_DOUBLE_CLICK:
                break;
        }
        processed = true;
    }
    return processed;
}
