/*
 * Copyright 2024 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "inverter_layer.h"
#include "menu_cell_layer.h"
#include "scroll_layer.h"

#include "applib/app_timer.h"
#include "applib/fonts/fonts.h"
#include "applib/graphics/text.h"

#include <stdint.h>
#include <stddef.h>

//! @file menu_layer.h
//! @addtogroup UI
//! @{
//!   @addtogroup Layer Layers
//!   @{
//!     @addtogroup MenuLayer
//! \brief Layer that displays a standard list menu. Data is provided using
//! callbacks.
//!
//! ![](menu_layer.png)
//! <h3>Key Points</h3>
//! * The familiar list-style menu widget, as used throughout the Pebble user
//! interface.
//! * Built on top of \ref ScrollLayer, inheriting all its goodness like
//! animated scrolling, automatic "more content" shadow indicators, etc.
//! * All data needed to render the menu is requested on-demand via callbacks,
//! to avoid the need to keep a lot of data in memory.
//! * Support for "sections". A section is a group of items, visually separated
//! by a header with the name at the top of the section.
//! * Variable heights: each menu item cell and each section header can have
//! its own height. The heights are provided by callbacks.
//! * Deviation from the Layer system for cell drawing: Each menu item does
//! _not_ have its own Layer (to minimize memory usage). Instead, a
//! drawing callback is set onto the \ref MenuLayer that is responsible
//! for drawing each menu item. The \ref MenuLayer will call this callback for each
//! menu item that is visible and needs to be rendered.
//! * Cell and header drawing can be customized by implementing a custom drawing
//! callback.
//! * A few "canned" menu cell drawing functions are provided for convenience,
//! which support the default menu cell layout with a title, optional subtitle
//! and icon.
//!
//! For short, static list menus, consider using \ref SimpleMenuLayer.
//!     @{

//! @internal
//! Constant to indicate that a menu item index is not found
#define MENU_INDEX_NOT_FOUND ((const uint16_t) ~0)

//////////////////////
// Menu Layer

struct MenuLayer;

//! Data structure to represent an menu item's position in a menu, by specifying
//! the section index and the row index within that section.
typedef struct MenuIndex {
  //! The index of the section
  uint16_t section;
  //! The index of the row within the section with index `.section`
  uint16_t row;
} MenuIndex;

//! Macro to create a MenuIndex
#define MenuIndex(section, row) ((MenuIndex){ (section), (row) })

//! Comparator function to determine the order of two MenuIndex values.
//! @param a Pointer to the menu index of the first item
//! @param b Pointer to the menu index of the second item
//! @return 0 if A and B are equal, 1 if A has a higher section & row
//! combination than B or else -1
int16_t menu_index_compare(const MenuIndex *a, const MenuIndex *b);

//! @internal
//! Data structure with geometric information of a cell at specific menu index.
//! This is used internally for caching.
typedef struct MenuCellSpan {
  int16_t y;
  int16_t h;
  int16_t sep;
  MenuIndex index;
} MenuCellSpan;

//! Function signature for the callback to get the number of sections in a menu.
//! @param menu_layer The \ref MenuLayer for which the data is requested
//! @param callback_context The callback context
//! @return The number of sections in the menu
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef uint16_t (*MenuLayerGetNumberOfSectionsCallback)(struct MenuLayer *menu_layer,
                                                         void *callback_context);

//! Function signature for the callback to get the number of rows in a
//! given section in a menu.
//! @param menu_layer The \ref MenuLayer for which the data is requested
//! @param section_index The index of the section of the menu for which the
//! number of items it contains is requested
//! @param callback_context The callback context
//! @return The number of rows in the given section in the menu
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef uint16_t (*MenuLayerGetNumberOfRowsInSectionsCallback)(struct MenuLayer *menu_layer,
                                                               uint16_t section_index,
                                                               void *callback_context);

//! Function signature for the callback to get the height of the menu cell
//! at a given index.
//! @param menu_layer The \ref MenuLayer for which the data is requested
//! @param cell_index The MenuIndex for which the cell height is requested
//! @param callback_context The callback context
//! @return The height of the cell at the given MenuIndex
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef int16_t (*MenuLayerGetCellHeightCallback)(struct MenuLayer *menu_layer,
                                                  MenuIndex *cell_index,
                                                  void *callback_context);

//! Function signature for the callback to get the height of the section header
//! at a given section index.
//! @param menu_layer The \ref MenuLayer for which the data is requested
//! @param section_index The index of the section for which the header height is
//! requested
//! @param callback_context The callback context
//! @return The height of the section header at the given section index
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef int16_t (*MenuLayerGetHeaderHeightCallback)(struct MenuLayer *menu_layer,
                                                    uint16_t section_index,
                                                    void *callback_context);

//! Function signature for the callback to get the height of the separator
//! at a given index.
//! @param menu_layer The \ref MenuLayer for which the data is requested
//! @param cell_index The MenuIndex for which the cell height is requested
//! @param callback_context The callback context
//! @return The height of the separator at the given MenuIndex
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef int16_t (*MenuLayerGetSeparatorHeightCallback)(struct MenuLayer *menu_layer,
                                                       MenuIndex *cell_index,
                                                       void *callback_context);

//! Function signature for the callback to render the menu cell at a given
//! MenuIndex.
//! @param ctx The destination graphics context to draw into
//! @param cell_layer The cell's layer, containing the geometry of the cell
//! @param cell_index The MenuIndex of the cell that needs to be drawn
//! @param callback_context The callback context
//! @note The `cell_layer` argument is provided to make it easy to re-use an
//! `.update_proc` implementation in this callback. Only the bounds and frame
//! of the `cell_layer` are actually valid and other properties should be
//! ignored.
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef void (*MenuLayerDrawRowCallback)(GContext* ctx,
                                         const Layer *cell_layer,
                                         MenuIndex *cell_index,
                                         void *callback_context);

//! Function signature for the callback to render the section header at a given
//! section index.
//! @param ctx The destination graphics context to draw into
//! @param cell_layer The header cell's layer, containing the geometry of the
//! header cell
//! @param section_index The section index of the section header that needs to
//! be drawn
//! @param callback_context The callback context
//! @note The `cell_layer` argument is provided to make it easy to re-use an
//! `.update_proc` implementation in this callback. Only the bounds and frame
//! of the `cell_layer` are actually valid and other properties should be
//! ignored.
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef void (*MenuLayerDrawHeaderCallback)(GContext* ctx,
                                            const Layer *cell_layer,
                                            uint16_t section_index,
                                            void *callback_context);

//! Function signature for the callback to render the separator at a given
//! MenuIndex.
//! @param ctx The destination graphics context to draw into
//! @param cell_layer The cell's layer, containing the geometry of the cell
//! @param cell_index The MenuIndex of the separator that needs to be drawn
//! @param callback_context The callback context
//! @note The `cell_layer` argument is provided to make it easy to re-use an
//! `.update_proc` implementation in this callback. Only the bounds and frame
//! of the `cell_layer` are actually valid and other properties should be
//! ignored.
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef void (*MenuLayerDrawSeparatorCallback)(GContext* ctx,
                                               const Layer *cell_layer,
                                               MenuIndex *cell_index,
                                               void *callback_context);

//! Function signature for the callback to handle the event that a user hits
//! the SELECT button.
//! @param menu_layer The \ref MenuLayer for which the selection event occurred
//! @param cell_index The MenuIndex of the cell that is selected
//! @param callback_context The callback context
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef void (*MenuLayerSelectCallback)(struct MenuLayer *menu_layer,
                                        MenuIndex *cell_index,
                                        void *callback_context);

//! Function signature for the callback to handle a change in the current
//! selected item in the menu.
//! @param menu_layer The \ref MenuLayer for which the selection event occurred
//! @param new_index The MenuIndex of the new item that is selected now
//! @param old_index The MenuIndex of the old item that was selected before
//! @param callback_context The callback context
//! @see \ref menu_layer_set_callbacks()
//! @see \ref MenuLayerCallbacks
typedef void (*MenuLayerSelectionChangedCallback)(struct MenuLayer *menu_layer,
                                                  MenuIndex new_index,
                                                  MenuIndex old_index,
                                                  void *callback_context);

//! Function signature for the callback which allows or changes selection behavior of the menu.
//! In order to change the cell that should be selected, modify the passed in new_index.
//! Preventing the selection from changing, new_index can be assigned the value of old_index.
//! @param menu_layer The \ref MenuLayer for which the selection event that occurred
//! @param new_index Pointer to the index that the MenuLayer is going to change selection to.
//! @param old_index The index that is being unselected.
//! @param callback_context The callback context
//! @note \ref menu_layer_set_selected_index will not trigger this callback when
//! the selection changes, but \ref menu_layer_set_selected_next will.
typedef void (*MenuLayerSelectionWillChangeCallback)(struct MenuLayer *menu_layer,
                                                     MenuIndex *new_index,
                                                     MenuIndex old_index,
                                                     void *callback_context);

//! Function signature for the callback which draws the menu's background.
//! The background is underneath the cells of the menu, and is visible in the
//! padding below the bottom cell, or if a cell's background color is set to \ref GColorClear.
//! @param ctx The destination graphics context to draw into.
//! @param bg_layer The background's layer, containing the geometry of the background.
//! @param highlight Whether this should be rendered as highlighted or not. Highlight style
//! should match the highlight style of cells, since this color can be used for animating selection.
typedef void (*MenuLayerDrawBackgroundCallback)(GContext* ctx,
                                                const Layer *bg_layer,
                                                bool highlight,
                                                void *callback_context);

//! Data structure containing all the callbacks of a \ref MenuLayer.
typedef struct MenuLayerCallbacks {
  //! Callback that gets called to get the number of sections in the menu.
  //! This can get called at various moments throughout the life of a menu.
  //! @note When `NULL`, the number of sections defaults to 1.
  MenuLayerGetNumberOfSectionsCallback get_num_sections;

  //! Callback that gets called to get the number of rows in a section. This
  //! can get called at various moments throughout the life of a menu.
  //! @note Must be set to a valid callback; `NULL` causes undefined behavior.
  MenuLayerGetNumberOfRowsInSectionsCallback get_num_rows;

  //! Callback that gets called to get the height of a cell.
  //! This can get called at various moments throughout the life of a menu.
  //! @note When `NULL`, the default height of \ref MENU_CELL_BASIC_CELL_HEIGHT pixels is used.
  //! Developers may wish to use \ref MENU_CELL_ROUND_FOCUSED_SHORT_CELL_HEIGHT
  //! and \ref MENU_CELL_ROUND_UNFOCUSED_SHORT_CELL_HEIGHT on a round display
  //! to respect the system aesthetic.
  MenuLayerGetCellHeightCallback get_cell_height;

  //! Callback that gets called to get the height of a section header.
  //! This can get called at various moments throughout the life of a menu.
  //! @note When `NULL`, the default height of 0 pixels is used. This disables
  //! section headers.
  MenuLayerGetHeaderHeightCallback get_header_height;

  //! Callback that gets called to render a menu item.
  //! This gets called for each menu item, every time it needs to be
  //! re-rendered.
  //! @note Must be set to a valid callback; `NULL` causes undefined behavior.
  MenuLayerDrawRowCallback draw_row;

  //! Callback that gets called to render a section header.
  //! This gets called for each section header, every time it needs to be
  //! re-rendered.
  //! @note Must be set to a valid callback, unless `.get_header_height` is
  //! `NULL`. Causes undefined behavior otherwise.
  MenuLayerDrawHeaderCallback draw_header;

  //! Callback that gets called when the user triggers a click with the SELECT
  //! button.
  //! @note When `NULL`, click events for the SELECT button are ignored.
  MenuLayerSelectCallback select_click;

  //! Callback that gets called when the user triggers a long click with the
  //! SELECT button.
  //! @note When `NULL`, long click events for the SELECT button are ignored.
  MenuLayerSelectCallback select_long_click;

  //! Callback that gets called whenever the selection changes.
  //! @note When `NULL`, selection change events are ignored.
  MenuLayerSelectionChangedCallback selection_changed;

  //! Callback that gets called to get the height of a separator
  //! This can get called at various moments throughout the life of a menu.
  //! @note When `NULL`, the default height of 0 is used.
  MenuLayerGetSeparatorHeightCallback get_separator_height;

  //! Callback that gets called to render a separator.
  //! This gets called for each separator, every time it needs to be
  //! re-rendered.
  //! @note Must be set to a valid callback, unless `.get_separator_height` is
  //! `NULL`. Causes undefined behavior otherwise.
  MenuLayerDrawSeparatorCallback draw_separator;

  //! Callback that gets called before the selected cell changes.
  //! This gets called before the selected item in the MenuLayer is changed,
  //! and will allow for the selected cell to be overridden.
  //! This allows for skipping cells in the menu, locking selection onto a given item,
  MenuLayerSelectionWillChangeCallback selection_will_change;

  //! Callback that gets called before any cells are drawn.
  //! This supports two states, either highlighted or not highlighted.
  //! If highlighted is specified, it is expected to be colored in the same
  //! style as the menu's cells are.
  //! If this callback is not specified, it will default to the colors set with
  //! \ref menu_layer_set_normal_colors and \ref menu_layer_set_highlight_colors.
  MenuLayerDrawBackgroundCallback draw_background;
} MenuLayerCallbacks;

enum {
  MenuLayerColorBackground = 0,
  MenuLayerColorForeground,
  MenuLayerColor_Count,
};
#ifndef __clang__
_Static_assert(MenuLayerColor_Count == 2, "Bad enum MenuLayerColor");
#endif

//! Data structure of a MenuLayer.
//! @note a `MenuLayer *` can safely be casted to a `Layer *` and
//! `ScrollLayer *` and can thus be used with all other functions that take a
//! `Layer *` or `ScrollLayer *`, respectively, as an argument.
//! <br/>For example, the following is legal:
//! \code{.c}
//! MenuLayer menu_layer;
//! ...
//! layer_set_hidden((Layer *)&menu_layer, true);
//! \endcode
//! @note However there are a few caveats:
//! * Do not try to change to bounds or frame of a \ref MenuLayer, after
//! initializing it.
typedef struct MenuLayer {
  ScrollLayer scroll_layer;
  InverterLayer inverter;
  //! @internal
  struct {
    //! @internal
    //! Cell index + geometry cache of a cell that was in frame during the last redraw
    MenuCellSpan cursor;
  } cache;
  //! @internal
  //! Selected cell index + geometry cache of the selected cell
  MenuCellSpan selection;
  MenuLayerCallbacks callbacks;
  void *callback_context;

  //! Default colors to be used for \ref MenuLayer.
  //! Use MenuLayerColorNormal and MenuLayerColorHighlight for indexing.
  GColor normal_colors[MenuLayerColor_Count];
  GColor highlight_colors[MenuLayerColor_Count];

  //! Animation used for selection. Note this is only used in 3.x+ apps, legacy2 apps don't
  //! use this.
  struct {
    Animation *animation;
    GRect target; //! The target frame of the animation
    //! cell_layer's bounds.origin will be modified by this to allow for
    //! content scrolling without scrolling the actual cells
    int16_t cell_content_origin_offset_y;
    //! used to express "bouncing" of the highlight
    int16_t selection_extend_top;
    //! same as selection_extend_top but for the bottom
    int16_t selection_extend_bottom;
    //! some animations (e.g. center focused) will use this field to postpone the update of
    //! menulayer.selection (especially for the .index)
    MenuCellSpan new_selection;
  } animation;

  //! @internal
  //! If true, there will be padding after the bottom item in the menu
  //! Defaults to 'true'
  bool pad_bottom:1;

  //! If true, the MenuLayer will generally scroll the content so that the selected row is
  //! on the center of the screen.
  bool center_focused:1;

  //! If true, the MenuLayer will not perform the selection cell clipping animation. This is
  //! independent of the scrolling animation.
  bool selection_animation_disabled:1;

  //! Add some padding to keep track of the \ref MenuLayer size budget.
  //! As long as the size stays within this budget, 2.x apps can safely use the 3.x MenuLayer type.
  //! When padding is removed, the assertion below should also be removed.
  uint8_t padding[44];
} MenuLayer;

//! Padding used below the last item in pixels
#define MENU_LAYER_BOTTOM_PADDING 20

//! Initializes a \ref MenuLayer with given frame
//! All previous contents are erased and the following default values are set:
//! * Clips: `true`
//! * Hidden: `false`
//! * Content size: `frame.size`
//! * Content offset: \ref GPointZero
//! * Callbacks: None (`NULL` for each one)
//! * Callback context: `NULL`
//! * After the relevant callbacks are called to populate the menu, the item at MenuIndex(0, 0)
//!   will be selected initially.
//! The layer is marked dirty automatically.
//! @param menu_layer The \ref MenuLayer to initialize
//! @param frame The frame with which to initialize the \ref MenuLayer
void menu_layer_init(MenuLayer *menu_layer, const GRect *frame);

//! Creates a new \ref MenuLayer on the heap and initializes it with the default values.
//!
//! * Clips: `true`
//! * Hidden: `false`
//! * Content size: `frame.size`
//! * Content offset: \ref GPointZero
//! * Callbacks: None (`NULL` for each one)
//! * Callback context: `NULL`
//! * After the relevant callbacks are called to populate the menu, the item at MenuIndex(0, 0)
//!   will be selected initially.
//! @return A pointer to the \ref MenuLayer. `NULL` if the \ref MenuLayer could not
//! be created
MenuLayer* menu_layer_create(GRect frame);

void menu_layer_deinit(MenuLayer* menu_layer);

//! Destroys a \ref MenuLayer previously created by menu_layer_create.
void menu_layer_destroy(MenuLayer* menu_layer);

//! Gets the "root" Layer of the \ref MenuLayer, which is the parent for the sub-
//! layers used for its implementation.
//! @param menu_layer Pointer to the MenuLayer for which to get the "root" Layer
//! @return The "root" Layer of the \ref MenuLayer.
//! @internal
//! @note The result is always equal to `(Layer *) menu_layer`.
Layer* menu_layer_get_layer(const MenuLayer *menu_layer);

//! Gets the ScrollLayer of the \ref MenuLayer, which is the layer responsible for
//! the scrolling of the \ref MenuLayer.
//! @param menu_layer Pointer to the \ref MenuLayer for which to get the ScrollLayer
//! @return The ScrollLayer of the \ref MenuLayer.
//! @internal
//! @note The result is always equal to `(ScrollLayer *) menu_layer`.
ScrollLayer* menu_layer_get_scroll_layer(const MenuLayer *menu_layer);

//! @internal
//! This function replaces \ref menu_layer_set_callbacks_by_value in order to change the callbacks
//! parameter to be passed by a pointer instead of being passed by value. Callers consume much less
//! code space when passing a pointer compared to passing structs by value.
//! @see menu_layer_set_callbacks_by_value
void menu_layer_set_callbacks(MenuLayer *menu_layer,
                              void *callback_context,
                              const MenuLayerCallbacks *callbacks);

//! Sets the callbacks for the MenuLayer.
//! @param menu_layer Pointer to the \ref MenuLayer for which to set the callbacks
//! and callback context.
//! @param callback_context The new callback context. This is passed into each
//! of the callbacks and can be set to point to application provided data.
//! @param callbacks The new callbacks for the \ref MenuLayer. The storage for this
//! data structure must be long lived. Therefore, it cannot be stack-allocated.
//! @see MenuLayerCallbacks
void menu_layer_set_callbacks_by_value(MenuLayer *menu_layer, void *callback_context,
                                       MenuLayerCallbacks callbacks);

//! Convenience function to set the \ref ClickConfigProvider callback on the
//! given window to the \ref MenuLayer internal click config provider. This internal
//! click configuration provider, will set up the default UP & DOWN
//! scrolling / menu item selection behavior.
//! This function calls \ref scroll_layer_set_click_config_onto_window to
//! accomplish this.
//!
//! Click and long click events for the SELECT button can be handled by
//! installing the appropriate callbacks using \ref menu_layer_set_callbacks().
//! This is a deviation from the usual click configuration provider pattern.
//! @param menu_layer The \ref MenuLayer that needs to receive click events.
//! @param window The window for which to set the click configuration.
//! @see \ref Clicks
//! @see \ref window_set_click_config_provider_with_context()
//! @see \ref scroll_layer_set_click_config_onto_window()
void menu_layer_set_click_config_onto_window(MenuLayer *menu_layer,
                                             struct Window *window);

//! This enables or disables padding at the bottom of the \ref MenuLayer.
//! Padding at the bottom of the layer keeps the bottom item from being at the very bottom of the
//! screen.
//! Padding is turned on by default for all MenuLayers.
//! The color of the padded area will be the background color set using
//! \ref menu_layer_set_normal_colors(). To color the padding a different color, use
//! \ref MenuLayerDrawBackgroundCallback.
//! @param menu_layer The menu layer for which to enable or disable the padding.
//! @param enable True = enable padding, False = disable padding.
void menu_layer_pad_bottom_enable(MenuLayer *menu_layer, bool enable);

//! Values to specify how a (selected) row should be aligned relative to the
//! visible area of the \ref MenuLayer.
typedef enum {
  //! Don't align or update the scroll offset of the \ref MenuLayer.
  MenuRowAlignNone,

  //! Scroll the contents of the \ref MenuLayer in such way that the selected row
  //! is centered relative to the visible area.
  MenuRowAlignCenter,

  //! Scroll the contents of the \ref MenuLayer in such way that the selected row
  //! is at the top of the visible area.
  MenuRowAlignTop,

  //! Scroll the contents of the \ref MenuLayer in such way that the selected row
  //! is at the bottom of the visible area.
  MenuRowAlignBottom,
} MenuRowAlign;

//! Selects the next or previous item, relative to the current selection.
//! @param menu_layer The \ref MenuLayer for which to select the next item
//! @param up Supply `false` to select the next item in the list (downwards),
//! or `true` to select the previous item in the list (upwards).
//! @param scroll_align The alignment of the new selection
//! @param animated Supply `true` to animate changing the selection, or `false`
//! to change the selection instantly.
//! @note If there is no next/previous item, this function is a no-op.
void menu_layer_set_selected_next(MenuLayer *menu_layer,
                                  bool up,
                                  MenuRowAlign scroll_align,
                                  bool animated);

//! Selects the item with given \ref MenuIndex.
//! @param menu_layer The \ref MenuLayer for which to change the selection
//! @param index The index of the item to select
//! @param scroll_align The alignment of the new selection
//! @param animated Supply `true` to animate changing the selection, or `false`
//! to change the selection instantly.
//! @note If the section and/or row index exceeds the available number of sections
//! or resp. rows, the exceeding index/indices will be capped, effectively
//! selecting the last section and/or row, resp.
void menu_layer_set_selected_index(MenuLayer *menu_layer,
                                   MenuIndex index, MenuRowAlign scroll_align,
                                   bool animated);

//! Gets the MenuIndex of the currently selected menu item.
//! @param menu_layer The \ref MenuLayer for which to get the current selected index.
//! @see menu_cell_layer_is_highlighted
//! @note This function should not be used to determine whether a cell should be
//! highlighted or not. See \ref menu_cell_layer_is_highlighted for more
//! information.
MenuIndex menu_layer_get_selected_index(const MenuLayer *menu_layer);

//! Returns whether or not the specified cell index is currently selected.
//! @param menu_layer The \ref MenuLayer to use when determining if the index is selected.
//! @param index The \ref MenuIndex of the cell to check for selection.
//! @note This function should not be used to determine whether a cell is highlighted or not.
//! See \ref menu_cell_layer_is_highlighted for more information.
bool menu_layer_is_index_selected(const MenuLayer *menu_layer, MenuIndex *index);

//! Reloads the data of the menu. This causes the menu to re-request the menu
//! item data, by calling the relevant callbacks.
//! The current selection and scroll position will not be changed. See the
//! note with \ref menu_layer_set_selected_index() for the behavior if the
//! old selection is no longer valid.
//! @param menu_layer The \ref MenuLayer for which to reload the data.
void menu_layer_reload_data(MenuLayer *menu_layer);

//! Set the default colors to be used for cells when it is in a normal state (not highlighted).
//! The GContext's text and fill colors will be set appropriately prior to calling the `.draw_row`
//! callback.
//! If this function is not explicitly called on a \ref MenuLayer, it will default to white
//! background with black foreground.
//! @param menu_layer The \ref MenuLayer for which to set the colors.
//! @param background The color to be used for the background of the cell.
//! @param foreground The color to be used for the foreground and text of the cell.
//! @see \ref menu_layer_set_highlight_colors
void menu_layer_set_normal_colors(MenuLayer *menu_layer, GColor background, GColor foreground);

//! Set the default colors to be used for cells when it is in a highlighted state.
//! The GContext's text and fill colors will be set appropriately prior to calling the `.draw_row`
//! callback.
//! If this function is not explicitly called on a \ref MenuLayer, it will default to black
//! background with white foreground.
//! @param menu_layer The \ref MenuLayer for which to set the colors.
//! @param background The color to be used for the background of the cell.
//! @param foreground The color to be used for the foreground and text of the cell.
//! @see \ref menu_layer_set_normal_colors
void menu_layer_set_highlight_colors(MenuLayer *menu_layer, GColor background, GColor foreground);


//! True, if the \ref MenuLayer generally scrolls such that the selected row is in the center.
//! @see \ref menu_layer_set_center_focused
bool menu_layer_get_center_focused(MenuLayer *menu_layer);

//! Controls if the \ref MenuLayer generally scrolls such that the selected row is in the center.
//! For platforms with a round display (PBL_ROUND) the default is true,
//! otherwise false is the default
//! @param menu_layer The menu layer for which to enable or disable the behavior.
//! @param center_focused true = enable the mode, false = disable it.
//! @see \ref menu_layer_get_center_focused
void menu_layer_set_center_focused(MenuLayer *menu_layer, bool center_focused);


//!     @} // end addtogroup MenuLayer
//!   @} // end addtogroup Layer
//! @} // end addtogroup UI

