/*
 * menu5_options.c
 * begin 20190613 true
 *
 * settings menu functions
 */

#include "ui/menu.h"

#include "render/font.h"

#include "hw/lightsense.h"

#include "user_config.h"

#include <stdio.h>
#include <string.h>



#define LI_ENABLE_LEDS      0
#define LI_NO_MOVE_SLP_TIME 1
#define LI_NO_MOVE_DIM_TIME 2
#define LI_NO_MOVE_THRESH   3
#define LI_WAKEUP_THRESH    4
#define LI_LSENS_DARK_CAL   5
#define LI_FACTORY_RESET    6
#define LI_DEBUG_SHOW_CPU   7
#define LI_DEBUG_SHOW_ACCEL 8



const uint16_t sleep_times[] = {
	0,
	60,
	300,
	600,
	900,
	1200,
	1800,
};



static uint8_t factory_reset;



void menu_5_disp(uint8_t idx)
{
	int8_t w, x;
	char txt[12];

	ssd1306fb_set_cursor(10, 7);

	uconf.flags &= ~UCONF_FLAGS_LEDS_DISABLE;

	// which item selected?
	switch (idx) {
		case LI_ENABLE_LEDS: {
			ssd1306fb_draw_str(font_table[0].font, "Enable LEDs", 1);
			strcpy(txt, (uconf.flags & UCONF_FLAGS_LEDS_ENABLE) ? "On" : "Off");
			break;
		}
		case LI_NO_MOVE_SLP_TIME: {
			ssd1306fb_draw_str(font_table[0].font, "No Movement Sleep Time", 0);
			if (uconf.sleep_timeout) {
				sprintf(txt, "%dmin", (uconf.sleep_timeout / 60));
			} else {
				strcpy(txt, "Off");
			}
			break;
		}
        case LI_NO_MOVE_DIM_TIME: {
            ssd1306fb_draw_str(font_table[0].font, "No Move LED Autodim Time", 0);
            if (uconf.dim_timeout) {
                sprintf(txt, "%dmin", (uconf.dim_timeout / 60));
            } else {
                strcpy(txt, "Off");
            }
            break;
        }
		case LI_NO_MOVE_THRESH: {
			ssd1306fb_draw_str(font_table[0].font, "No Movement Threshold", 0);
			strcpy(txt, "Normal");
			break;
		}
		case LI_WAKEUP_THRESH: {
			ssd1306fb_draw_str(font_table[0].font, "Wakeup Threshold", 1);
			strcpy(txt, "Normal");
			break;
		}
		case LI_LSENS_DARK_CAL: {
			// constantly save value at this screen
			uconf.lsens_dark_thresh = lsens_get_dark_threshold();
			// ensure LEDs are disabled when calibrating
			uconf.flags |= UCONF_FLAGS_LEDS_DISABLE;
			
			ssd1306fb_draw_str(font_table[0].font, "Recal Lightsense DARK RM!", 0);
			sprintf(txt, "%d", uconf.lsens_dark_thresh);
			break;
		}
		case LI_FACTORY_RESET: {
		    uint32_t iter;

		    // todo: implement manual button checking here after getting button orientation code working
		    //       yes, this means reset speed depends on framerate lol
		    if (btn_pushed & (1 << 2)) {
		        factory_reset++;
		    } else factory_reset = 0;

		    if (factory_reset >= 32) {
		        // do the factory reset
		        iter = uconf.iter;
		        uconf_defaults();

		        // we do store the old iteration value so long as it isn't
		        // too high in order to keep track of nvmem writes.
		        // if the value is unnaturally high, we'll reset to zero.
		        // if it's corrupt in any way, enjoy your false write count.
		        if (iter < 0xffffff) {
		            uconf.iter = iter;
		        }

		        uconf_clear();

                // while it isn't necesasry to write an initial config
                // as the code will determine there is no valid config
                // and load defaults if the nvmem is empty,
                // we're doing it to write the iter value.
		        uconf_write();

		        // aaaand it's gone
		        SYS_ResetExecute();

		        while (1);
		    }

		    ssd1306fb_draw_str(font_table[0].font, "Hold Set to Factory Reset...", 0);
		    txt[0] = 0;

		    ssd1306fb_draw_rect(52, 18, 52 + 31, 31);
		    for (w = 0; w < factory_reset; w++) {
		        ssd1306fb_draw_vline(53 + w, 18, 31);
		    }
		    break;
		}
		case LI_DEBUG_SHOW_CPU: {
			ssd1306fb_draw_str(font_table[0].font, "Debug: Show CPU%", 1);
			strcpy(txt, (uconf.flags & UCONF_FLAGS_SHOW_CPU_USAGE) ? "Yes" : "No");
			break;
		}
		case LI_DEBUG_SHOW_ACCEL: {
			ssd1306fb_draw_str(font_table[0].font, "Debug: Show Accel", 1);
			strcpy(txt, (uconf.flags & UCONF_FLAGS_SHOW_ACCEL_ANGLE) ? "Yes" : "No");
			break;
		}
	}

	if (strlen(txt)) {
        w = ssd1306fb_get_str_width(font_DejaVu_Sans_Mono_Bold_11, txt, strlen(txt), 1);
        x = 68 - (w >> 1);
        ssd1306fb_set_cursor(x, 18);
        ssd1306fb_draw_str(font_DejaVu_Sans_Mono_Bold_11, txt, 1);

        // draw box
        ssd1306fb_draw_rect(x - 2, 18, x + w + 2, 31);
	}

	// draw extras
	menu_draw_tabs(idx);

	menu_draw_buttons(MENU_BTNSTYLE_MENU, 0x0f);
}

void menu_5_enter(uint8_t idx)
{
	int i, j;
	uint16_t *t;
	
	switch (idx) {
		case LI_ENABLE_LEDS: {
			if (uconf.flags & UCONF_FLAGS_LEDS_ENABLE) {
				uconf.flags &= ~UCONF_FLAGS_LEDS_ENABLE;
			} else {
				uconf.flags |=  UCONF_FLAGS_LEDS_ENABLE;
			}
			break;
		}
		case LI_NO_MOVE_SLP_TIME:
		case LI_NO_MOVE_DIM_TIME: {
		    t = (idx == LI_NO_MOVE_SLP_TIME) ? &uconf.sleep_timeout : &uconf.dim_timeout;

			j = sizeof(sleep_times) / sizeof(sleep_times[0]);
			for (i = 0; i < j; i++) {
				if (*t == sleep_times[i]) {
					i++;
					i %= j;
					*t = sleep_times[i];
					j = 0xff;
					break;
				}
			}

			// couldn't find a match, so set default
			if (j != 0xff) {
				*t = sleep_times[4];
			}
			break;
		}
		case LI_LSENS_DARK_CAL: {
			// reset sensor threshold to recal value
			lsens_set_dark_threshold(0xffff);
			break;
		}
		case LI_FACTORY_RESET: {
		    break;
		}
		case LI_DEBUG_SHOW_CPU: {
			if (uconf.flags & UCONF_FLAGS_SHOW_CPU_USAGE) {
				uconf.flags &= ~UCONF_FLAGS_SHOW_CPU_USAGE;
			} else {
				uconf.flags |=  UCONF_FLAGS_SHOW_CPU_USAGE;
			}
			break;
		}
		case LI_DEBUG_SHOW_ACCEL: {
			if (uconf.flags & UCONF_FLAGS_SHOW_ACCEL_ANGLE) {
				uconf.flags &= ~UCONF_FLAGS_SHOW_ACCEL_ANGLE;
			} else {
				uconf.flags |=  UCONF_FLAGS_SHOW_ACCEL_ANGLE;
			}
			break;
		}
	}
}
