/* Copyright 2022 Christopher Swenson
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include QMK_KEYBOARD_H
enum planck_layers {
    _ENIGMA,
    _QWERTY,
    _FN,
    _LOWER,
    _RAISE
};
enum planck_normal_keycodes {
    QWERTY = SAFE_RANGE,
    ENIGMA,
    EN_A,
    EN_B,
    EN_C,
    EN_D,
    EN_E,
    EN_F,
    EN_G,
    EN_H,
    EN_I,
    EN_J,
    EN_K,
    EN_L,
    EN_M,
    EN_N,
    EN_O,
    EN_P,
    EN_Q,
    EN_R,
    EN_S,
    EN_T,
    EN_U,
    EN_V,
    EN_W,
    EN_X,
    EN_Y,
    EN_Z,
    EN_RES,
    EN_TEST,
    EN_DIAG,
    EN_BSPC,
    EN_SREF,
    EN_SROT,
    EN_SPOS,
    EN_SRIN,
    EN_SPLU
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* Enigma
    * ,-----------------------------------------------------------------------------------.
    * | Esc  |   Q  |   W  |   E  |   R  |   T  |   Y  |   U  |   I  |   O  |   P  | Bksp |
    * |------+------+------+------+------+-------------+------+------+------+------+------|
    * | Tab  |   A  |   S  |   D  |   F  |   G  |   H  |   J  |   K  |   L  |   ;  |  "   |
    * |------+------+------+------+------+------|------+------+------+------+------+------|
    * | Shift|   Z  |   X  |   C  |   V  |   B  |   N  |   M  |   ,  |   .  |   /  |Enter |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | Ctrl |  Fn  | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
    * `-----------------------------------------------------------------------------------'
    */
    [_ENIGMA] = LAYOUT_planck_mit(
        QK_GESC, EN_Q,    EN_W,    EN_E,    EN_R,       EN_T,    EN_Y, EN_U,       EN_I,    EN_O,    EN_P,    KC_BSPC,
        KC_TAB,  EN_A,    EN_S,    EN_D,    EN_F,       EN_G,    EN_H, EN_J,       EN_K,    EN_L,    KC_SCLN, KC_QUOT,
        KC_LSFT, EN_Z,    EN_X,    EN_C,    EN_V,       EN_B,    EN_N, EN_M,       KC_COMM, KC_DOT,  KC_SLSH, KC_ENT,
        KC_LCTL, MO(_FN), KC_LGUI, KC_LALT, MO(_LOWER),    KC_SPC,     MO(_RAISE), KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
    ),
    /* Qwerty
    * ,-----------------------------------------------------------------------------------.
    * | Esc  |   Q  |   W  |   E  |   R  |   T  |   Y  |   U  |   I  |   O  |   P  | Bksp |
    * |------+------+------+------+------+-------------+------+------+------+------+------|
    * | Tab  |   A  |   S  |   D  |   F  |   G  |   H  |   J  |   K  |   L  |   ;  |  "   |
    * |------+------+------+------+------+------|------+------+------+------+------+------|
    * | Shift|   Z  |   X  |   C  |   V  |   B  |   N  |   M  |   ,  |   .  |   /  |Enter |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | Ctrl |  Fn  | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
    * `-----------------------------------------------------------------------------------'
    */
    [_QWERTY] = LAYOUT_planck_mit(
        QK_GESC, KC_Q,    KC_W,    KC_E,    KC_R,      KC_T,    KC_Y,    KC_U,       KC_I,    KC_O,    KC_P,    KC_BSPC,
        KC_TAB,  KC_A,    KC_S,    KC_D,    KC_F,      KC_G,    KC_H,    KC_J,       KC_K,    KC_L,    KC_SCLN, KC_QUOT,
        KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,      KC_B,    KC_N,    KC_M,       KC_COMM, KC_DOT,  KC_SLSH, KC_ENT,
        KC_LCTL, MO(_FN), KC_LGUI, KC_LALT, MO(_LOWER),    KC_SPC,       MO(_RAISE), KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
    ),
    /* Function
    * ,-----------------------------------------------------------------------------------.
    * | Boot | Reset| Diag |      |      |      |      |      |      |      | Test |Revers|
    * |------+------+------+------+------+-------------+------+------+------+------+------|
    * |      |      |      |      |      |      |      |      |      |      |      |      |
    * |------+------+------+------+------+------|------+------+------+------+------+------|
    * |      |Reflec|Rotors|Posn.s|Rings |Plugs |      |      |Enigma|Qwerty|      |      |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * |      |      |      |      |      |             |      |      |      |      |      |
    * `-----------------------------------------------------------------------------------'
    */
    [_FN] = LAYOUT_planck_mit(
        QK_BOOT, EN_RES,  EN_DIAG, _______, _______, _______, _______, _______, _______, _______, EN_TEST, EN_BSPC,
        _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
        _______, EN_SREF, EN_SROT, EN_SPOS, EN_SRIN, EN_SPLU, _______, _______, QWERTY,  ENIGMA,  _______, _______,
        _______, _______, _______, _______, _______,      _______,     _______, _______, _______, _______, _______
    ),
    /* Lower
    * ,-----------------------------------------------------------------------------------.
    * | ~    |   !  |   @  |   #  |   $  |   %  |   ^  |   &  |   *  |   (  |   )  | Bksp |
    * |------+------+------+------+------+-------------+------+------+------+------+------|
    * |      |      |      |      |      |      |      |   _  |   +  |   {  |   }  |  |   |
    * |------+------+------+------+------+------|------+------+------+------+------+------|
    * | Shift|      |      |      |      |      |      |      |      |      |      |      |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | Ctrl |  Fn  | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
    * `-----------------------------------------------------------------------------------'
    */
    [_LOWER] = LAYOUT_planck_mit(
        KC_TILD, KC_EXLM, KC_AT,   KC_HASH, KC_DLR,  KC_PERC, KC_CIRC, KC_AMPR,  KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC, 
        _______, _______, _______, _______, _______, _______, _______, KC_UNDS,  KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, 
        KC_LSFT, _______, _______, _______, _______, _______, _______,  _______, _______, _______, _______, _______, 
        KC_LCTL, _______, KC_LGUI, KC_LALT, _______,       KC_SPC,      _______, KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
    ),
    /* RAISE
    * ,-----------------------------------------------------------------------------------.
    * | `    |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |   9  |   0  | Bksp |
    * |------+------+------+------+------+-------------+------+------+------+------+------|
    * |      |      |      |      |      |      |      |   -  |   =  |   [  |   ]  |  \   |
    * |------+------+------+------+------+------|------+------+------+------+------+------|
    * | Shift|      |      |      |      |      |      |      |      |      |      |      |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | Ctrl |  Fn  | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
    * `-----------------------------------------------------------------------------------'
    */
    [_RAISE] = LAYOUT_planck_mit(
        KC_GRV,  KC_1,    KC_2,    KC_3,    KC_4,    KC_5,    KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_BSPC, 
        _______, _______, _______, _______, _______, _______, _______, KC_MINS, KC_EQL,  KC_LBRC, KC_RBRC, KC_BSLS, 
        KC_LSFT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, 
        KC_LCTL, _______, KC_LGUI, KC_LALT, _______,      KC_SPC,      _______, KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
    ),
};
char rotor_definitions[5][26] = {
    "EKMFLGDQVZNTOWYHXUSPAIBRCJ",
    "AJDKSIRUXBLHWTMCQGZNPYFVOE",
    "BDFHJLCPRTXVZNYEIWGAKMUSQO",
    "ESOVPZJAYQUIRHXLNFTGKDCMWB",
    "VZBRGITYUPSDNHLXAWMJQOFECK" 
};
char reflector_definitions[3][26] = {
    "EJMZALYXVBWFCRQUONTSPIKHGD",
    "YRUHQSLDPXNGOKMIEBFZCWVJAT",
    "FVPJIAOYEDRZXWGCTKUQSBNMHL"
};
char notch[5] = "QEVJZ";
typedef struct Settings {
    char rotor_order[3];
    char rotor_rings[3];
    char rotor_positions[3];
    char plugs[25];
    int plug_count;
    char reflector;
} Settings;
typedef struct KeyboardState {
    bool is_setting_reflector;
    bool is_setting_rotors;
    bool is_setting_rotor_positions;
    bool is_setting_rotor_rings;
    bool is_setting_plugs;
    char setting_progress[26];
    int setting_index;
    Settings current_settings;
    Settings default_settings;
} KeyboardState;
int bound(int letter) {
    return ((letter % 26) + 26) % 26;
}
char to_char(int letter) {
    return 'A' + letter;
}
int to_int(char letter) {
    return letter - 'A';
}
char encipher(char letter, Settings *settings) {
    int rotor_2_step = settings->rotor_positions[2] == notch[settings->rotor_order[2] - 1];
    int rotor_1_step = settings->rotor_positions[1] == notch[settings->rotor_order[1] - 1];
      
    // Advance the third rotor
    settings->rotor_positions[2]++;
    if (settings->rotor_positions[2] > 'Z') {
      settings->rotor_positions[2] -= 26;
    }
    // Maybe advance the second rotor, including double steps
    if (rotor_2_step || rotor_1_step) {
        settings->rotor_positions[1]++;
        if (settings->rotor_positions[1] > 'Z') {
            settings->rotor_positions[1] -= 26;
        }
    }
    // Maybe advance the first rotor
    if (rotor_1_step) {
        settings->rotor_positions[0]++;
        if (settings->rotor_positions[0] > 'Z') {
            settings->rotor_positions[0] -= 26;
        }
    }
    // Swap letters on plugboard
    for (int i = 0; i < settings->plug_count * 2; i += 2) {
        if (letter == settings->plugs[i]) {
            letter = settings->plugs[i + 1];
        } else if (letter == settings->plugs[i + 1]) {
            letter = settings->plugs[i];
        }  
    }
    // Rotors (right to left)
    for (int rotor_index = 2; rotor_index >= 0; rotor_index--) {
        char *rotor_definition = rotor_definitions[settings->rotor_order[rotor_index] - 1];
        int position = to_int(settings->rotor_positions[rotor_index]);
        int ring = to_int(settings->rotor_rings[rotor_index]);
        int char_index = to_int(letter);
        letter = to_char(bound(
            to_int(rotor_definition[bound(char_index + position - ring)]) + ring - position
        ));
    }
    // Swap via reflector
    letter = reflector_definitions[to_int(settings->reflector)][to_int(letter)];
    // Rotors in reverse (left to right)
    for (int rotor_index = 0; rotor_index < 3; rotor_index++) {
        char *rotor_definition = rotor_definitions[settings->rotor_order[rotor_index] - 1];
        int position = to_int(settings->rotor_positions[rotor_index]);
        int ring = to_int(settings->rotor_rings[rotor_index]);
        int search_index;
        for (search_index = 0; search_index < 26; search_index++) {
            if (
                rotor_definition[search_index] 
                == to_char(bound(to_int(letter) - ring + position))
            ) {
                break;
            }
        }
        letter = to_char(bound(search_index - position + ring));
    }
    
    // Plugboard again
    for (int i = 0; i < settings->plug_count * 2; i += 2) {
        if (letter == settings->plugs[i]) {
            letter = settings->plugs[i + 1];
        } else if (letter == settings->plugs[i + 1]) {
            letter = settings->plugs[i];
        }
    }
    return letter;
}
void init_enigma_default(Settings *settings) {
    settings->rotor_order[0] = 1;
    settings->rotor_rings[0] = 'A';
    settings->rotor_positions[0] = 'A';
    settings->rotor_order[1] = 2;
    settings->rotor_rings[1] = 'A';
    settings->rotor_positions[1] = 'A';
    settings->rotor_order[2] =  3;
    settings->rotor_rings[2] = 'A';
    settings->rotor_positions[2] = 'A';
    strcpy(settings->plugs, "");
    settings->plug_count = 0;
    settings->reflector = 'B';
}
void copy_settings(Settings *from, Settings *to) {
    to->rotor_order[0] = from->rotor_order[0];
    to->rotor_rings[0] = from->rotor_rings[0];
    to->rotor_positions[0] = from->rotor_positions[0];
    to->rotor_order[1] = from->rotor_order[1];
    to->rotor_rings[1] = from->rotor_rings[1];
    to->rotor_positions[1] = from->rotor_positions[1];
    to->rotor_order[2] = from->rotor_order[2];
    to->rotor_rings[2] = from->rotor_rings[2];
    to->rotor_positions[2] = from->rotor_positions[2];
    strncpy(to->plugs, from->plugs, from->plug_count * 2);
    to->plug_count = from->plug_count;
    to->reflector = from->reflector;
}
char *rotor_name(int rotor_number) {
    if (rotor_number == 1) {
        return "I";
    } else if (rotor_number == 2) {
        return "II";
    } else if (rotor_number == 3) {
        return "III";
    } else if (rotor_number == 4) {
        return "IV";
    } else if (rotor_number == 5) {
        return "V";
    }
    return "?";
}
void rotors_reverse(Settings *settings) {
    int rotor_2_step = settings->rotor_positions[2] 
        == to_char(bound(to_int(notch[settings->rotor_order[2] - 1]) + 1));
    int rotor_1_step = settings->rotor_positions[1] 
        == to_char(bound(to_int(notch[settings->rotor_order[1] - 1]) + 1));
      
    // Reverse third rotor
    settings->rotor_positions[2]--;
    if (settings->rotor_positions[2] < 'A') {
        settings->rotor_positions[2] += 26;
    }
    // Maybe reverse second rotor (including double steps)
    if (rotor_2_step || rotor_1_step) {
        settings->rotor_positions[1]--;
        if (settings->rotor_positions[1] < 'A') {
            settings->rotor_positions[1] += 26;
        }
    }
    // Maybe recerse first rotor
    if (rotor_1_step) {
        settings->rotor_positions[0]--;
        if (settings->rotor_positions[0] < 'A') {
            settings->rotor_positions[0] += 26;
        }
    }
}
void reset_settings(KeyboardState *state) {
  copy_settings(&state->default_settings, &state->current_settings);
}
void set_layer(uint8_t default_layer) {
    default_layer_set((layer_state_t)1 << default_layer);
}
void set_backlight(uint8_t mode, uint8_t hue, uint8_t sat, uint8_t val) {
    #ifdef RGBLIGHT_ENABLE
        rgblight_enable_noeeprom(); 
        rgblight_mode_noeeprom(mode);
        rgblight_sethsv_noeeprom(hue, sat, val);
    #endif
}
void clear_working_settings(KeyboardState *state) {
    state->is_setting_reflector = false;
    state->is_setting_rotors = false;
    state->is_setting_rotor_positions = false;
    state->is_setting_rotor_rings = false;
    state->is_setting_plugs = false;
    state->setting_index = 0;
    set_layer(_ENIGMA);
    set_backlight(RGBLIGHT_MODE_STATIC_LIGHT, HSV_RED);
}
void send_settings_string(Settings *settings) {
    send_char(settings->reflector);
    send_string(". ");
    send_string(rotor_name(settings->rotor_order[0]));
    send_char(settings->rotor_rings[0]);
    send_string("-");
    send_string(rotor_name(settings->rotor_order[1]));
    send_char(settings->rotor_rings[1]);
    send_string("-");
    send_string(rotor_name(settings->rotor_order[2]));
    send_char(settings->rotor_rings[2]);
    send_string(" (");
    send_char(settings->rotor_positions[0]);
    send_string(", ");
    send_char(settings->rotor_positions[1]);
    send_string(", ");
    send_char(settings->rotor_positions[2]);
    send_string(") ");
    for (int i = 0; i < settings->plug_count; i++) {
        send_char(settings->plugs[i * 2]);
        send_char(settings->plugs[i * 2 + 1]);
        send_string(" ");
    }
    send_string("\n");
}
void perform_test(Settings *settings) {
    for (int i = 0; i < 1000; i++) {
        send_char(encipher('A', settings) - ('A' - 'a'));
    }
}
void commit_plug_settings(KeyboardState *state) {
    state->default_settings.plug_count = state->setting_index / 2; 
    for (int i = 0; i < state->default_settings.plug_count; i++) {
        state->default_settings.plugs[i * 2] = state->setting_progress[i * 2];
        state->default_settings.plugs[i * 2 + 1] = state->setting_progress[i * 2 + 1];
    }
    reset_settings(state);
    clear_working_settings(state);
}
void handle_set_reflector(char letter, KeyboardState *state) {
    if (letter >= 'A' && letter <= 'C') {
        state->default_settings.reflector = letter;
        reset_settings(state);
        clear_working_settings(state);
    }
}
bool handle_set_rotor(char letter, KeyboardState *state) {
    bool is_valid = letter >= 'A' && letter <= 'E' && state->setting_index < 3;
    if (is_valid) {
        state->setting_progress[state->setting_index] = to_int(letter) + 1;
        state->setting_index += 1;
        if (state->setting_index == 3) {
            state->default_settings.rotor_order[0] = state->setting_progress[0];
            state->default_settings.rotor_order[1] = state->setting_progress[1];
            state->default_settings.rotor_order[2] = state->setting_progress[2];
            reset_settings(state);
            clear_working_settings(state);
        }
    }
    return is_valid;
}
bool handle_set_rotor_position(char letter, KeyboardState *state) {
    bool is_valid = state->setting_index < 3; // Guaranteed to be A-Z already
    if (is_valid) {
        state->setting_progress[state->setting_index] = letter;
        state->setting_index += 1;
        if (state->setting_index == 3) {
            state->default_settings.rotor_positions[0] = state->setting_progress[0];
            state->default_settings.rotor_positions[1] = state->setting_progress[1];
            state->default_settings.rotor_positions[2] = state->setting_progress[2]; 
            reset_settings(state);
            clear_working_settings(state);
        }
    }
    return is_valid;
}
bool handle_set_rotor_ring(char letter, KeyboardState *state) {
    bool is_valid = state->setting_index < 3;
    if (is_valid) {
        state->setting_progress[state->setting_index] = letter;
        state->setting_index += 1;
        if (state->setting_index == 3) {
            state->default_settings.rotor_rings[0] = state->setting_progress[0];
            state->default_settings.rotor_rings[1] = state->setting_progress[1];
            state->default_settings.rotor_rings[2] = state->setting_progress[2];
            reset_settings(state);
            clear_working_settings(state);
        }
    }
    return is_valid;
}
bool handle_set_plug(char letter, KeyboardState *state) {
    bool is_valid = state->setting_index < 26;
    if (is_valid) {
        state->setting_progress[state->setting_index] = letter;
        state->setting_index += 1;
    }
    return is_valid;
}
void handle_enigma_keypress(char letter, bool any_mods, KeyboardState *state) {
    bool settings_valid = true;
    if (letter) {
        if (any_mods) {
            tap_code(KC_A + to_int(letter));
        } else if (state->is_setting_reflector) {
            handle_set_reflector(letter, state);
        } else if (state->is_setting_rotors) {
            settings_valid = handle_set_rotor(letter, state);
        } else if (state->is_setting_rotor_positions) {
            settings_valid = handle_set_rotor_position(letter, state);
        } else if (state->is_setting_rotor_rings) {
            settings_valid = handle_set_rotor_ring(letter, state);
        } else if (state->is_setting_plugs) {
            settings_valid = handle_set_plug(letter, state);
        } else {
            char c2 = encipher(letter, &state->current_settings);
            send_char(c2 - ('A' - 'a'));
        }
    }
    if (!settings_valid) {
        clear_working_settings(state);
    }
}
KeyboardState STATE;
void keyboard_pre_init_user(void) {
    init_enigma_default(&STATE.default_settings);
    init_enigma_default(&STATE.current_settings);
    clear_working_settings(&STATE);
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    uint8_t letter_index;
    bool letter_found = false;
    if (record->event.pressed) {
        switch (keycode) {
          case QWERTY:
              set_layer(_QWERTY);
              set_backlight(RGBLIGHT_MODE_RAINBOW_SWIRL + 4, HSV_PURPLE);
              break;
          case ENIGMA:
              set_layer(_ENIGMA);
              set_backlight(RGBLIGHT_MODE_STATIC_LIGHT, HSV_RED);
              break;
          case EN_SREF:
              reset_settings(&STATE);
              STATE.is_setting_reflector = true;
              set_layer(_ENIGMA);
              set_backlight(RGBLIGHT_MODE_SNAKE, HSV_RED);
              break;
          case EN_SROT:
              reset_settings(&STATE);
              STATE.is_setting_rotors = true;
              STATE.setting_index = 0;
              set_layer(_ENIGMA);
              set_backlight(RGBLIGHT_MODE_SNAKE, 10, 255, 255);
              break;
          case EN_SPOS:
              reset_settings(&STATE);
              STATE.is_setting_rotor_positions = true;
              STATE.setting_index = 0;
              set_layer(_ENIGMA);
              set_backlight(RGBLIGHT_MODE_SNAKE, HSV_ORANGE);
              break;
          case EN_SRIN:
              reset_settings(&STATE);
              STATE.is_setting_rotor_rings = true;
              STATE.setting_index = 0;
              set_layer(_ENIGMA);
              set_backlight(RGBLIGHT_MODE_SNAKE, HSV_GREEN);
              break;
          case EN_SPLU:
              reset_settings(&STATE);
              STATE.is_setting_plugs = true;
              STATE.setting_index = 0;
              set_layer(_ENIGMA);
              set_backlight(RGBLIGHT_MODE_SNAKE, HSV_BLUE);
              break;
          case QK_GESC:
              if (
                  STATE.is_setting_reflector
                  || STATE.is_setting_rotors
                  || STATE.is_setting_rotor_positions
                  || STATE.is_setting_rotor_rings
                  || STATE.is_setting_plugs
              ) {
                  clear_working_settings(&STATE);
                  return false;
              }
              break;
          case KC_ENT:
              if (STATE.is_setting_plugs) { 
                  commit_plug_settings(&STATE);
                  return false;
              }
              break;
          case EN_A ... EN_Z:
              letter_index = keycode - EN_A;
              letter_found = true;
              break;
          case EN_RES:
              reset_settings(&STATE);
              break;
          case EN_TEST:
              perform_test(&STATE.current_settings);
              break;
          case EN_DIAG:
              send_settings_string(&STATE.current_settings);
              break;
          case EN_BSPC:
              rotors_reverse(&STATE.current_settings);
              tap_code(KC_BSPC);
              break;
      }
    }
    char letter = letter_found ? 'A' + letter_index : 0;
    uint8_t mods = get_mods();
    bool any_mods = (mods & MOD_MASK_CTRL) || (mods & MOD_MASK_ALT) || (mods & MOD_MASK_GUI);
    handle_enigma_keypress(letter, any_mods, &STATE);
    return true;
}
void keyboard_post_init_user(void) {
    set_layer(_QWERTY);
    set_backlight(RGBLIGHT_MODE_RAINBOW_SWIRL + 4, HSV_PURPLE);
}