88 lines
3.3 KiB
Python
88 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from custom_components.powercalc.configuration.normalization import normalize_state_trigger
|
|
from custom_components.powercalc.const import (
|
|
CONF_FIXED_VALUE,
|
|
CONF_PLAYBOOK_ID,
|
|
CONF_POWER,
|
|
CONF_POWER_TEMPLATE,
|
|
CONF_STATE,
|
|
CONF_STATE_TRIGGER,
|
|
CONF_STATES_POWER,
|
|
CalculationStrategy,
|
|
)
|
|
from custom_components.powercalc.flow_helper.common import unwrap_choose_selector, wrap_choose_selector
|
|
|
|
FIXED_CHOICES: dict[str, list[str] | str] = {
|
|
CONF_STATES_POWER: CONF_STATES_POWER,
|
|
CONF_POWER_TEMPLATE: CONF_POWER_TEMPLATE,
|
|
CONF_POWER: CONF_POWER,
|
|
}
|
|
|
|
|
|
def order_choices_for_default[T](
|
|
choices: dict[str, T],
|
|
default_choice: str | None,
|
|
) -> dict[str, T]:
|
|
"""Put the default choice first because HA initializes choose selectors from the first choice."""
|
|
if default_choice not in choices:
|
|
return choices
|
|
return {
|
|
default_choice: choices[default_choice],
|
|
**{choice: config for choice, config in choices.items() if choice != default_choice},
|
|
}
|
|
|
|
|
|
def has_saved_choice_value(value: object) -> bool:
|
|
"""Return whether a saved strategy value should drive the selected form choice."""
|
|
if value is None:
|
|
return False
|
|
if isinstance(value, (str, list, dict)):
|
|
return bool(value)
|
|
return True
|
|
|
|
|
|
def find_present_choice(form_data: dict[str, Any], choices: dict[str, list[str] | str]) -> str | None:
|
|
"""Find the first choice that has matching config data."""
|
|
for choice_id, mapping in choices.items():
|
|
keys = [mapping] if isinstance(mapping, str) else mapping
|
|
if any(has_saved_choice_value(form_data.get(key)) for key in keys):
|
|
return choice_id
|
|
return None
|
|
|
|
|
|
def fixed_choice_key_from_validated_value(value: object) -> str:
|
|
"""Infer the fixed strategy config key from a validated ChooseSelector value."""
|
|
if isinstance(value, list):
|
|
return CONF_STATES_POWER
|
|
if isinstance(value, str):
|
|
return CONF_POWER_TEMPLATE
|
|
return CONF_POWER
|
|
|
|
|
|
def unwrap_strategy_user_input(strategy: CalculationStrategy, user_input: dict[str, Any]) -> dict[str, Any]:
|
|
"""Unwrap form-only selector wrappers and normalize strategy user input."""
|
|
if strategy == CalculationStrategy.FIXED:
|
|
unwrap_choose_selector(user_input, CONF_FIXED_VALUE, fixed_choice_key_from_validated_value)
|
|
if CONF_STATE_TRIGGER in user_input:
|
|
user_input[CONF_STATE_TRIGGER] = normalize_state_trigger(user_input[CONF_STATE_TRIGGER])
|
|
return user_input
|
|
|
|
|
|
def wrap_strategy_form_data(strategy: CalculationStrategy, form_data: dict[str, Any]) -> dict[str, Any]:
|
|
"""Wrap stored strategy config back into form-only selector structures."""
|
|
if strategy == CalculationStrategy.FIXED:
|
|
choices = order_choices_for_default(FIXED_CHOICES, find_present_choice(form_data, FIXED_CHOICES))
|
|
form_data = wrap_choose_selector(form_data, CONF_FIXED_VALUE, choices, raw_value=True)
|
|
if CONF_STATE_TRIGGER in form_data and isinstance(form_data[CONF_STATE_TRIGGER], dict):
|
|
form_data = {
|
|
**form_data,
|
|
CONF_STATE_TRIGGER: [
|
|
{CONF_STATE: state, CONF_PLAYBOOK_ID: playbook_id}
|
|
for state, playbook_id in form_data[CONF_STATE_TRIGGER].items()
|
|
],
|
|
}
|
|
return form_data
|