import esphome.codegen as cg
from esphome.components import lcd_base
from esphome.components.display_menu_base import (
    DISPLAY_MENU_BASE_SCHEMA,
    DisplayMenuComponent,
    display_menu_to_code,
)
import esphome.config_validation as cv
from esphome.const import CONF_DIMENSIONS, CONF_DISPLAY_ID, CONF_ID
from esphome.core.entity_helpers import inherit_property_from

CODEOWNERS = ["@numo68"]

AUTO_LOAD = ["display_menu_base"]

lcd_menu_ns = cg.esphome_ns.namespace("lcd_menu")

CONF_MARK_SELECTED = "mark_selected"
CONF_MARK_EDITING = "mark_editing"
CONF_MARK_SUBMENU = "mark_submenu"
CONF_MARK_BACK = "mark_back"

MINIMUM_COLUMNS = 12

LCDCharacterMenuComponent = lcd_menu_ns.class_(
    "LCDCharacterMenuComponent", DisplayMenuComponent
)

MULTI_CONF = True


def validate_lcd_dimensions(config):
    if config[CONF_DIMENSIONS][0] < MINIMUM_COLUMNS:
        raise cv.Invalid(
            f"LCD display must have at least {MINIMUM_COLUMNS} columns to be usable with the menu"
        )
    return config


CONFIG_SCHEMA = DISPLAY_MENU_BASE_SCHEMA.extend(
    cv.Schema(
        {
            cv.GenerateID(): cv.declare_id(LCDCharacterMenuComponent),
            cv.GenerateID(CONF_DISPLAY_ID): cv.use_id(lcd_base.LCDDisplay),
            cv.Optional(CONF_MARK_SELECTED, default=0x3E): cv.uint8_t,
            cv.Optional(CONF_MARK_EDITING, default=0x2A): cv.uint8_t,
            cv.Optional(CONF_MARK_SUBMENU, default=0x7E): cv.uint8_t,
            cv.Optional(CONF_MARK_BACK, default=0x5E): cv.uint8_t,
        }
    )
)

FINAL_VALIDATE_SCHEMA = cv.All(
    inherit_property_from(CONF_DIMENSIONS, CONF_DISPLAY_ID),
    validate_lcd_dimensions,
)


async def to_code(config):
    var = cg.new_Pvariable(config[CONF_ID])
    await cg.register_component(var, config)
    disp = await cg.get_variable(config[CONF_DISPLAY_ID])
    cg.add(var.set_display(disp))
    cg.add(var.set_dimensions(config[CONF_DIMENSIONS][0], config[CONF_DIMENSIONS][1]))
    await display_menu_to_code(var, config)
    cg.add(var.set_mark_selected(config[CONF_MARK_SELECTED]))
    cg.add(var.set_mark_editing(config[CONF_MARK_EDITING]))
    cg.add(var.set_mark_submenu(config[CONF_MARK_SUBMENU]))
    cg.add(var.set_mark_back(config[CONF_MARK_BACK]))
