#include "rf_cmd.h"

// Includes
#include "term.h"
#include "led.h"
#include "cfg.h"

// ============================================================================
//                                   GLOBALS
// ============================================================================

rf_cmd_t rf_cmd;

// ============================================================================
//                                PROTOTYPES
// ============================================================================


// ============================================================================
//                                 FUNCTION
// ============================================================================

void rf_cmd_init()
{
    rf_cmd.is_ready = false;
}

void rf_cmd_task()
{
    /*
    if (rf_cmd.is_ready == true){
        term_out_int(HAL_GetTick());
        term_out_char('-');
        term_out_int(rf_cmd.tick);
        term_out_char('>');
        term_out_int(rf_cmd.delay);
        term_out_str("\r\n");
    }
    */

    // Checkif command is available and delay is achieve
    if (rf_cmd.is_ready == false || (HAL_GetTick() - rf_cmd.tick) < rf_cmd.delay) return;
    rf_cmd.is_ready = false;
    uint8_t cmd = rf_cmd.cmd;

    /*
    term_out_str("CMD ");
    term_out_hex(cmd, 2);
    term_out_str("\r\n");
    */


    // SYNC
    if (RF_CMD_IS_SYNC(cmd)){


        if (cmd == RF_CMD_ID_LED_OFF){
            // LED_OFF
            led_set_color(LED_COLOR_OFF);
            led.seq.head.type = LED_SEQ_TYPE_NONE;

        }else if((cmd & RF_CMD_ID_SEQ_EXE_MASK) == RF_CMD_ID_SEQ_EXE){
            // SEQ_EXE
            uint8_t sid = RF_CMD_SEQ_GET_ID(cmd);
            cfg_seq_t * seq = &cfg.user.seq[sid];
            switch(seq->type){
                case RF_SEQ_TYPE_NONE:
                    return;
                    break;
                case RF_SEQ_TYPE_FLASH:
                    led_set_seq(LED_SEQ_BLINK(seq->count, rf_seq_to_led_color(seq->flash.on_color), seq->flash.on_ms * 100, rf_seq_to_led_color(seq->flash.off_color), seq->flash.off_ms * 100));
                    break;
                case RF_SEQ_TYPE_GLOW:
                    led_set_seq(LED_SEQ_GLOW(seq->count, rf_seq_to_led_color(seq->glow.a_color), rf_seq_to_led_color(seq->glow.b_color), seq->glow.a2b_ms * 100, seq->glow.b2a_ms * 100));
                    break;
            }
        }else{


            switch(cmd & RF_CMD_ID_LED_MASK){
                case RF_CMD_ID_LED_ON:
                    //LED_ON
                    led.seq.head.type = LED_SEQ_TYPE_NONE;
                    led_set_color(rf_led_to_led_color(cmd & ~RF_CMD_ID_LED_MASK));

                    break;
                case RF_CMD_ID_LED_FLASH:
                    // LED_FLASH
                    led_set_seq(LED_SEQ_BLINK(1, rf_led_to_led_color(cmd & ~RF_CMD_ID_LED_MASK), cfg.user.flash_on_ms, LED_COLOR_OFF, 0));
                    break;
                case RF_CMD_ID_LED_FLASHC:
                    // LED_FLASHC
                    led_set_seq(LED_SEQ_BLINK(0, rf_led_to_led_color(cmd & ~RF_CMD_ID_LED_MASK), cfg.user.flash_on_ms, LED_COLOR_OFF, cfg.user.flash_off_ms));
                    break;
                case RF_CMD_ID_LED_GLOW:
                    // LED_GLOW
                    led_set_seq(LED_SEQ_GLOW(1, LED_COLOR_OFF, rf_led_to_led_color(cmd & ~RF_CMD_ID_LED_MASK), 1000, 1000));
                    break;
                case RF_CMD_ID_LED_GLOWC:
                    // LED_GLOWC
                    led_set_seq(LED_SEQ_GLOW(0, LED_COLOR_OFF, rf_led_to_led_color(cmd & ~RF_CMD_ID_LED_MASK), 1000, 1000));
                    break;
                default:
            }

        }

    // LED_COLOR
    }else if(cmd == RF_CMD_ID_TRUE_COLOR){
        if (rf_cmd.psize != 3) return;
        led_color_t tcolor;
        tcolor.as.r = rf_cmd.payload[0];
        tcolor.as.g = rf_cmd.payload[1];
        tcolor.as.b = rf_cmd.payload[2];
        tcolor.as.a = 0;
        led.seq.head.type = LED_SEQ_TYPE_NONE;
        led_set_color(tcolor);

    // UNSYNC
    }else{
        uint8_t psize = rf_cmd.psize;
        uint8_t *payload = rf_cmd.payload;
        // CONFIG
        if (cmd >= RF_CMD_ID_SET_ACK && cmd <= RF_CMD_ID_SEQ_CLR){
            switch(cmd){
                case RF_CMD_ID_SET_ACK:
                    // SET_ACK
                    if (psize != 1) return;
                    cfg.user.is_ack = payload[0];
                    break;
                case RF_CMD_ID_SET_AUTOSAVE:
                    // SET_AUTOSAVE
                    if (psize != 1) return;
                    cfg.user.is_autosave = payload[0];
                    break;
                 case RF_CMD_ID_SET_LED_COUNT:
                     // SET_LED_COUNT
                    if (psize != 1) return;
                    cfg.user.led_count = (payload[0] > BUILD_LED_COUNT ? BUILD_LED_COUNT : payload[0]);
                    break;
                 case RF_CMD_ID_SET_BRIGHT:
                     // SET_BRIGHT
                    if (psize != 1) return;
                    cfg.user.brightness = payload[0];
                    led.brightness = payload[0];
                    break;
                case RF_CMD_ID_SET_BOOT:
                    // SET_BOOT
                    if (psize != 1) return;
                    if (payload[0] == 0x17) cfg.user.boot = CFG_BOOT_AUTO;
                    else if (payload[0] == 0x96) cfg.user.boot = CFG_BOOT_RF;
                    break;
                 case RF_CMD_ID_SET_FLASH:
                     // SET_FLASH
                    if (psize != 2) return;
                    cfg.user.flash_on_ms    = payload[0] * 100;
                    cfg.user.flash_off_ms   = payload[1] * 100;
                    break;
                 case RF_CMD_ID_SET_GLOW:
                     // SET_GLOW
                    if (psize != 2) return;
                    cfg.user.glow_a2b_ms    = payload[0] * 100;
                    cfg.user.glow_b2a_ms    = payload[1] * 100;
                    break;
                case RF_CMD_ID_GRP_JOIN:
                    // GRP_JOIN
                    if (psize != 1) return;
                    if (cfg_group_is_member(payload[0]) == true) return;
                    cfg_group_join(payload[0]);
                    break;
                case RF_CMD_ID_GRP_LEAVE:
                    // GRP_LEAVE
                    if (psize != 1) return;
                    if (cfg_group_is_member(payload[0]) == false) return;
                    cfg_group_leave(payload[0]);
                    break;
                case RF_CMD_ID_GRP_CLR:
                    // GRP_CLR
                    if (psize != 2) return;
                    if (payload[0] != 0xC3 || payload[1] != 0xF6) return;
                    cfg_group_clear();
                    break;
                case RF_CMD_ID_SEQ_SET:
                    // SEQ_SET
                    if (psize < 2 || psize > 7) return;
                    uint8_t sid = payload[0];
                    if (sid > 63) return;
                    cfg_seq_t * seq = &cfg.user.seq[sid];
                    if (payload[1] == RF_SEQ_TYPE_NONE){
                            // SEQ_TYPE_NONE
                        if (psize != 2) return;
                        seq->type = RF_SEQ_TYPE_NONE;
                    }else if (payload[1] == RF_SEQ_TYPE_FLASH){
                        // SEQ_TYPE_FLASH
                        if (psize != 7) return;
                        seq->type             = RF_SEQ_TYPE_FLASH;
                        seq->count            = payload[2];
                        seq->flash.on_color   = payload[3];
                        seq->flash.on_ms      = payload[4];
                        seq->flash.off_color  = payload[5];
                        seq->flash.off_ms     = payload[6];
                    }else if (payload[1] == RF_SEQ_TYPE_GLOW){
                        // SEQ_TYPE_GLOW
                        if (psize != 7) return;
                        seq->type             = RF_SEQ_TYPE_GLOW;
                        seq->count            = payload[2];
                        seq->glow.a_color     = payload[3];
                        seq->glow.b_color     = payload[4];
                        seq->glow.a2b_ms      = payload[5];
                        seq->glow.b2a_ms      = payload[6];
                    }
                    break;
                case RF_CMD_ID_SEQ_CLR:
                    // SEQ_CLR
                    if (psize != 2) return;
                    if (payload[0] != 0xB5 || payload[1] != 0x84) return;
                    cfg_sequence_clear();
                    break;
            }
            // Write config
            if (cfg.user.is_autosave) cfg_write_user();
            // Ack
            if (cfg.user.is_ack && led.seq.head.type == LED_SEQ_TYPE_NONE )  led_set_seq(LED_SEQ_BLINK(1, LED_COLOR_GREEN, 100, LED_COLOR_OFF, 0));

        }else if (cmd == RF_CMD_ID_RF_TEST){
            // RF_TEST
            rf_cmd.payload[rf_cmd.psize] = 0;
            term_out_msg((char*)rf_cmd.payload);
            led_set_seq(LED_SEQ_BLINK(1, LED_COLOR_GREEN, 200, LED_COLOR_OFF, 0));
        }else{
            if (psize != 2) return;
            switch(cmd){
                case RF_CMD_ID_SAVE:
                    // SAVE
                    if (payload[0] != 0x17 || payload[1] != 0xF2) return;
                    cfg_write_user();
                    break;
                case RF_CMD_ID_REBOOT:
                    // REBOOT
                    if (payload[0] != 0x32 || payload[1] != 0xB9) return;
                    system_reboot();
                    break;
                case RF_CMD_ID_SHUTDOWN:
                    // SHUTDOWN
                    if (payload[0] != 0x8F || payload[1] != 0x55) return;
                    system_shutdown();
                    break;
                case RF_CMD_ID_RESET:
                    // RESET
                    if (payload[0] != 0x73 || payload[1] != 0x84) return;
                    cfg_user_reset();
                    system_reboot();
                    break;

            }
        }

    }

}

led_color_t rf_led_to_led_color(uint8_t rf_led_color)
{
    switch(rf_led_color){
        case RF_COLOR_NONE:     return led_get_rand_color(); break;
        case RF_COLOR_BLUE:     return LED_COLOR_BLUE; break;
        case RF_COLOR_GREEN:    return LED_COLOR_GREEN; break;
        case RF_COLOR_CYAN:     return LED_COLOR_CYAN; break;
        case RF_COLOR_RED:      return LED_COLOR_RED; break;
        case RF_COLOR_MAGENTA:  return LED_COLOR_MAGENTA; break;
        case RF_COLOR_YELLOW:   return LED_COLOR_YELLOW; break;
        case RF_COLOR_WHITE:    return LED_COLOR_WHITE; break;
        default:                return LED_COLOR_OFF; break;
    }
}

led_color_t rf_seq_to_led_color(uint8_t rf_seq_color)
{
    switch(rf_seq_color){
        case RF_COLOR_NONE:     return LED_COLOR_OFF; break;
        case RF_COLOR_BLUE:     return LED_COLOR_BLUE; break;
        case RF_COLOR_GREEN:    return LED_COLOR_GREEN; break;
        case RF_COLOR_CYAN:     return LED_COLOR_CYAN; break;
        case RF_COLOR_RED:      return LED_COLOR_RED; break;
        case RF_COLOR_MAGENTA:  return LED_COLOR_MAGENTA; break;
        case RF_COLOR_YELLOW:   return LED_COLOR_YELLOW; break;
        case RF_COLOR_WHITE:    return LED_COLOR_WHITE; break;
        case RF_COLOR_RAND:     return led_get_rand_color(); break;
        case RF_COLOR_XRAND:    return led_get_rand_color(); break;
        case RF_COLOR_PREV:     return led.led_status[0]; break;
        default:                return LED_COLOR_OFF; break;
    }
}



