#ifndef CHAR_LCD_H
#define CHAR_LCD_H

#include <cstdint>

#define CHAR_LCD_I2C_NUM I2C_NUM_0

#define LCD_ADDR 0x27
#define LCD_ROWS 4
#define LCD_COLS 20

/// @brief Initializes the 2004 Character LCD
void init_lcd();

/// @brief Clear the LCD
void lcd_clear(bool no_lock = false);

/// @brief Move cursor to home position
void lcd_cursor_home(bool no_lock = false);

/// @brief Turn the display on/off
void lcd_set_display(bool display, bool no_lock = false);

/// @brief Turn the cursor's visibility on/off
void lcd_set_cursor_vis(bool cursor, bool no_lock = false);

/// @brief Turn blinking cursor on/off
void lcd_set_cursor_blink(bool blink, bool no_lock = false);

/// @brief Scroll the display left
void lcd_scroll_display_left(bool no_lock = false);
/// @brief Scroll the display right
void lcd_scroll_display_right(bool no_lock = false);

/// @brief Set the text to flows automatically left to right
void lcd_left_to_right(bool no_lock = false);
/// @brief Set the text to flows automatically right to left
void lcd_right_to_left(bool no_lock = false);

/// @brief Turn on/off autoscroll
void lcd_set_autoscroll(bool autoscroll, bool no_lock = false);

/// @brief Set backlight brightness
void lcd_set_backlight(bool backlight, bool no_lock = false);

/// @brief Create a custom character. You get 8 custom characters.
/// You can print custom characters by using escape characters in strings:
/// use '\x01' - '\x07' for custom characters 1-7. Use '\x08' for custom char 0.
void lcd_create_char(uint8_t location, const uint8_t charmap[], bool no_lock = false);

/// @brief Print a string to the LCD at a given pos. 
/// @param row the row the print the string at.
/// @param col the column to print the string at.
/// @param str the string to print.
void lcd_print(uint8_t row, uint8_t col, const char* str, bool no_lock = false);

/// @brief Enables or disables the header on the LCD.
/// @param enable `true` to enable the header, `false` to disable.
void set_lcd_header_enabled(bool enable);

/// @brief Returns weather or not the lcd_header is enabled.
/// @return `true` if the header is enabled, `false` otherwise.
bool lcd_header_enabled();

/// @brief Prints the header in the LCD.
void lcd_print_header();

/// @brief Prints the splash screen for the BLK_BOX.
void lcd_do_splash();

/// @brief Locks the LCD to allow chaining multiple commands without interuptions.
///
/// Commands you call while you lock the LCD, you must call with the `no_lock` flag set to true.
///
/// Do not hold this lock for an extended period of time.
/// @return `true` iff the lock was aquired.
bool lcd_lock(uint32_t ticks_to_wait);

/// @brief Unlocks the LCD to give away the mutex access to it.
void lcd_unlock();

/// @brief Set the resting position for the cursor
/// @param row the row where the cursor should rest
/// @param col the column where the cursor should rest
void lcd_set_cursor_resting_position(uint8_t row, uint8_t col);

/// @brief Get the current resting position of the cursor
/// @param row pointer to store the resting row
/// @param col pointer to store the resting column
void lcd_get_cursor_resting_position(uint8_t* row, uint8_t* col);

/// @brief Check if the cursor is currently visible
/// @return true if cursor is visible, false otherwise
bool lcd_is_cursor_visible();

#endif /* CHAR_LCD_H */
