# yaml-language-server: $schema=null
#:########################################################################################:#
# TITLE: NSPANEL LOUNGE CONTROLLER
# zorruno.com Home Assistant package
#:########################################################################################:#
# VERSIONS:
# V1.5 2026-05-19
# - Added Reading button brightness display.
# - Reading brightness is shown as the highest brightness percentage of either
#   couch spot light.
# - Changed Balanced button icon to mdi:scale / \uE472.
# - Added startup panel page refresh before full button state refresh.
#
# V1.4 2026-05-19
# - Changed button highlighting to targeted updates.
# - Remembered scene changes update only the old scene button and new scene button.
# - Reading/Dining changes update only the Reading and Dining buttons.
# - Full refresh is only used at HA start or when manually called.
# - ON icon colour is black [0, 0, 0].
# - OFF icon colour is white [255, 255, 255].
#
# V1.3 2026-05-19
# - Tested page refresh method, but it did not reliably refresh remembered scenes.
#
# V1.2 2026-05-19
# - Added explicit NSPanel button refresh actions using esphome.esp_nspanel2lounge_button.
# - Button states were pushed to the NSPanel when lounge_last_scene or the
#   Reading/Dining light states changed.
#
# V1.1 2026-05-18
# - Added template switches so remembered lighting scenes can stay highlighted
#   on the NSPanel button page.
# - Updated Blueprint button entities from script.* to switch.*.
#
# V1.0 2026-05-18
# - Initial NSPanel Lounge Controller package using NSPanel Easy Blueprint.
#:########################################################################################:#
# PURPOSE:
# - Configures the Lounge NSPanel Easy button page.
# - Provides Home Assistant script wrappers for lounge lighting scene actions.
# - Provides template switches for NSPanel button state/highlighting.
# - Pushes targeted NSPanel button highlight updates when relevant states change.
#:########################################################################################:#
# OPERATION NOTES:
# - The NSPanel display is configured by the NSPanel Easy Blueprint automation.
# - The screen buttons point to switch.nspanel_lounge_scene_* entities.
# - Remembered scenes are highlighted from input_text.lounge_last_scene.
# - Reading On/Off is highlighted from either couch spot light being on.
# - Reading On/Off shows the highest couch spot brightness percentage.
# - Dining On/Off is highlighted from the dining table light being on.
# - Pressing any NSPanel touch button activates the assigned scene/action.
# - Normal remembered scene transitions update only:
#     a) the previous remembered scene button to OFF
#     b) the new remembered scene button to ON
#:########################################################################################:#
# DEPENDENCIES:
# - script.lounge_set_scene
# - input_text.lounge_last_scene
# - light.esp_lounge6chdimmer_couch_spots_left
# - light.esp_lounge6chdimmer_couch_spots_right
# - light.esp_lounge6chdimmer_dining_table_light
# - NSPanel Easy Blueprint:
#     edwardtfn/nspanel_easy_blueprint.yaml
# - ESPHome actions:
#     esphome.esp_nspanel2lounge_button
#     esphome.esp_nspanel2lounge_command
#:########################################################################################:#
# NOTES:
# - This is Home Assistant package YAML, not ESPHome YAML.
# - The nspanel_name value is the Home Assistant device ID selected by the
#   Blueprint dropdown. Do not replace it with an entity_id or ESPHome hostname.
# - The icon values used by esphome.esp_nspanel2lounge_button are HASP/Nextion
#   icon codepoints, not mdi: icon names.
#:########################################################################################:#

#:########################################################################################:#
# AUTOMATIONS
#:########################################################################################:#

automation:
  #:######################################################################################:#
  # AUTOMATION: NSPanel Easy Blueprint Instance
  #:######################################################################################:#
  - id: nspanel_lounge_controller
    alias: "NSPanel Lounge Controller"
    description: "NSPanel Easy configuration for the lounge lighting scene panel."
    use_blueprint:
      path: edwardtfn/nspanel_easy_blueprint.yaml
      input:
        nspanel_name: 369e58c3779ff3dd9a0b4c59fadeac4f

        ########################################################################
        # BUTTON PAGE 01: Lounge Lighting Scenes
        ########################################################################
        button_page01_label: Lounge Lighting Scenes
        button_pages_icon_size: "10"

        entity01: switch.nspanel_lounge_scene_bright
        entity01_name: "Bright"
        entity01_icon: mdi:brightness-7
        entity01_confirm: false

        entity02: switch.nspanel_lounge_scene_tv_general
        entity02_name: "TV General"
        entity02_icon: mdi:television
        entity02_confirm: false

        entity03: switch.nspanel_lounge_scene_movie
        entity03_name: "Movie"
        entity03_icon: mdi:movie-open
        entity03_confirm: false

        entity04: switch.nspanel_lounge_scene_balanced
        entity04_name: "Balance"
        entity04_icon: mdi:scale
        entity04_confirm: false

        entity05: switch.nspanel_lounge_scene_warm_cozy
        entity05_name: "Warm Cozy"
        entity05_icon: mdi:fireplace
        entity05_confirm: false

        entity06: switch.nspanel_lounge_scene_reading
        entity06_name: "Reading On/Off"
        entity06_icon: mdi:book-open-page-variant
        entity06_confirm: false

        entity07: switch.nspanel_lounge_scene_dining
        entity07_name: "Dining On/Off"
        entity07_icon: mdi:silverware-fork-knife
        entity07_confirm: false

        entity08: switch.nspanel_lounge_scene_all_off
        entity08_name: "All Off"
        entity08_icon: mdi:power
        entity08_confirm: false
    mode: single

  #:######################################################################################:#
  # AUTOMATION: Refresh Remembered Scene Button Highlights
  #
  # Only updates the previous remembered scene button and the new remembered
  # scene button when input_text.lounge_last_scene changes.
  #:######################################################################################:#
  - id: nspanel_lounge_refresh_remembered_scene_buttons
    alias: "NSPanel Lounge - Refresh Remembered Scene Buttons"
    description: "Update only the old and new remembered scene buttons on the NSPanel."
    mode: restart
    trigger:
      - platform: state
        entity_id: input_text.lounge_last_scene

    action:
      - delay:
          milliseconds: 500

      - variables:
          old_scene: "{{ trigger.from_state.state if trigger.from_state is not none else '' }}"
          new_scene: "{{ trigger.to_state.state if trigger.to_state is not none else states('input_text.lounge_last_scene') }}"
          remembered_scenes:
            - "Bright"
            - "TV General"
            - "Balanced"
            - "Movie"
            - "Warm Cozy"
            - "All Off"

      - choose:
          - conditions: "{{ old_scene in remembered_scenes and old_scene != new_scene }}"
            sequence:
              - action: script.nspanel_lounge_push_scene_button_state
                data:
                  scene_name: "{{ old_scene }}"
                  button_state: false

      - delay:
          milliseconds: 100

      - choose:
          - conditions: "{{ new_scene in remembered_scenes }}"
            sequence:
              - action: script.nspanel_lounge_push_scene_button_state
                data:
                  scene_name: "{{ new_scene }}"
                  button_state: true

  #:######################################################################################:#
  # AUTOMATION: Refresh Reading And Dining Button Highlights
  #
  # Reading/Dining are toggle/action scenes, so they are updated from the real
  # light states rather than input_text.lounge_last_scene.
  #:######################################################################################:#
  - id: nspanel_lounge_refresh_toggle_scene_buttons
    alias: "NSPanel Lounge - Refresh Toggle Scene Buttons"
    description: "Update Reading and Dining buttons when their lights change."
    mode: restart
    trigger:
      - platform: state
        entity_id:
          - light.esp_lounge6chdimmer_couch_spots_left
          - light.esp_lounge6chdimmer_couch_spots_right
          - light.esp_lounge6chdimmer_dining_table_light

      - platform: state
        entity_id:
          - light.esp_lounge6chdimmer_couch_spots_left
          - light.esp_lounge6chdimmer_couch_spots_right
          - light.esp_lounge6chdimmer_dining_table_light
        attribute: brightness

    action:
      - delay:
          milliseconds: 500

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "Reading On/Off"
          button_state: >-
            {{
              (
                is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on')
                and (state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0)) > 0
              )
              or
              (
                is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on')
                and (state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0)) > 0
              )
            }}

      - delay:
          milliseconds: 100

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "Dining On/Off"
          button_state: >-
            {{
              is_state('light.esp_lounge6chdimmer_dining_table_light', 'on')
              and (state_attr('light.esp_lounge6chdimmer_dining_table_light', 'brightness') | int(0)) > 0
            }}

  #:######################################################################################:#
  # AUTOMATION: Initial NSPanel Button Refresh
  #
  # Full refresh happens when HA starts, or when the NSPanel comes back online.
  # Normal scene changes update only the required buttons.
  #:######################################################################################:#
  - id: nspanel_lounge_refresh_all_buttons_on_start
    alias: "NSPanel Lounge - Refresh All Buttons On Start"
    description: "Refresh all NSPanel lounge buttons when HA starts or the panel reconnects."
    mode: restart
    trigger:
      - platform: homeassistant
        event: start

      - platform: state
        entity_id: number.lounge_nspanel_touchscreen_display_brightness
        from: "unavailable"

      - platform: state
        entity_id: number.lounge_nspanel_touchscreen_display_brightness
        from: "unknown"

    action:
      - delay:
          seconds: 20

      - action: esphome.esp_nspanel2lounge_command
        data:
          cmd: "page buttonpage01"

      - delay:
          seconds: 1

      - action: script.nspanel_lounge_refresh_all_button_states

#:########################################################################################:#
# SCRIPTS
#:########################################################################################:#

script:
  #:######################################################################################:#
  # SCRIPTS: NSPanel Lounge Scene Button Actions
  #:######################################################################################:#
  nspanel_lounge_scene_bright:
    alias: "NSPanel Lounge Scene - Bright"
    mode: single
    sequence:
      - action: script.lounge_set_scene
        data:
          scene_name: "Bright"

  nspanel_lounge_scene_tv_general:
    alias: "NSPanel Lounge Scene - TV General"
    mode: single
    sequence:
      - action: script.lounge_set_scene
        data:
          scene_name: "TV General"

  nspanel_lounge_scene_movie:
    alias: "NSPanel Lounge Scene - Movie"
    mode: single
    sequence:
      - action: script.lounge_set_scene
        data:
          scene_name: "Movie"

  nspanel_lounge_scene_balanced:
    alias: "NSPanel Lounge Scene - Balanced"
    mode: single
    sequence:
      - action: script.lounge_set_scene
        data:
          scene_name: "Balanced"

  nspanel_lounge_scene_warm_cozy:
    alias: "NSPanel Lounge Scene - Warm Cozy"
    mode: single
    sequence:
      - action: script.lounge_set_scene
        data:
          scene_name: "Warm Cozy"

  nspanel_lounge_scene_reading:
    alias: "NSPanel Lounge Scene - Reading"
    mode: single
    sequence:
      - action: script.lounge_set_scene
        data:
          scene_name: "Reading On/Off"

  nspanel_lounge_scene_dining:
    alias: "NSPanel Lounge Scene - Dining"
    mode: single
    sequence:
      - action: script.lounge_set_scene
        data:
          scene_name: "Dining On/Off"

  nspanel_lounge_scene_all_off:
    alias: "NSPanel Lounge Scene - All Off"
    mode: single
    sequence:
      - action: script.lounge_set_scene
        data:
          scene_name: "All Off"

  #:######################################################################################:#
  # SCRIPT: Push One NSPanel Button State
  #
  # ON state:
  # - Button highlighted
  # - Icon colour black [0, 0, 0]
  #
  # OFF state:
  # - Button not highlighted
  # - Icon colour white [255, 255, 255]
  #:######################################################################################:#
  nspanel_lounge_push_button_state:
    alias: "NSPanel Lounge - Push Button State"
    mode: queued
    max: 20
    fields:
      button_id:
        description: "NSPanel button id, for example button01"
      button_state:
        description: "True for highlighted, false for normal"
      icon_code:
        description: "HASwitchPlate/Nextion icon codepoint"
      button_label:
        description: "Button label text"
      button_bri:
        description: "Optional brightness/value text shown on the NSPanel button"
    sequence:
      - variables:
          button_is_on: >-
            {{
              button_state in [true, 'true', 'True', 'on', 'On', '1', 1]
            }}
          button_bri_text: "{{ button_bri if button_bri is defined else '' }}"

      - choose:
          - conditions: "{{ button_is_on }}"
            sequence:
              - action: esphome.esp_nspanel2lounge_button
                data:
                  page: buttonpage01
                  id: "{{ button_id }}"
                  state: true
                  icon: "{{ icon_code }}"
                  icon_color:
                    - 0
                    - 0
                    - 0
                  icon_font: 10
                  bri: "{{ button_bri_text }}"
                  label: "{{ button_label }}"
                  is_page_render: false

        default:
          - action: esphome.esp_nspanel2lounge_button
            data:
              page: buttonpage01
              id: "{{ button_id }}"
              state: false
              icon: "{{ icon_code }}"
              icon_color:
                - 255
                - 255
                - 255
              icon_font: 10
              bri: "{{ button_bri_text }}"
              label: "{{ button_label }}"
              is_page_render: false

  #:######################################################################################:#
  # SCRIPT: Push One Scene Button State
  #
  # Maps scene/action names to NSPanel button ids, labels and icon codepoints.
  #:######################################################################################:#
  nspanel_lounge_push_scene_button_state:
    alias: "NSPanel Lounge - Push Scene Button State"
    mode: queued
    max: 20
    fields:
      scene_name:
        description: "Lounge scene/action name"
      button_state:
        description: "True for highlighted, false for normal"
    sequence:
      - choose:
          - conditions: "{{ scene_name == 'Bright' }}"
            sequence:
              - action: script.nspanel_lounge_push_button_state
                data:
                  button_id: button01
                  button_state: "{{ button_state }}"
                  icon_code: "\uE0E0"
                  button_label: "Bright"
                  button_bri: ""

          - conditions: "{{ scene_name == 'TV General' }}"
            sequence:
              - action: script.nspanel_lounge_push_button_state
                data:
                  button_id: button02
                  button_state: "{{ button_state }}"
                  icon_code: "\uE502"
                  button_label: "TV General"
                  button_bri: ""

          - conditions: "{{ scene_name == 'Movie' }}"
            sequence:
              - action: script.nspanel_lounge_push_button_state
                data:
                  button_id: button03
                  button_state: "{{ button_state }}"
                  icon_code: "\uEFCE"
                  button_label: "Movie"
                  button_bri: ""

          - conditions: "{{ scene_name == 'Balanced' }}"
            sequence:
              - action: script.nspanel_lounge_push_button_state
                data:
                  button_id: button04
                  button_state: "{{ button_state }}"
                  icon_code: "\uE472"
                  button_label: "Balance"
                  button_bri: ""

          - conditions: "{{ scene_name == 'Warm Cozy' }}"
            sequence:
              - action: script.nspanel_lounge_push_button_state
                data:
                  button_id: button05
                  button_state: "{{ button_state }}"
                  icon_code: "\uEE2E"
                  button_label: "Warm Cozy"
                  button_bri: ""

          - conditions: "{{ scene_name == 'Reading On/Off' }}"
            sequence:
              - action: script.nspanel_lounge_push_button_state
                data:
                  button_id: button06
                  button_state: "{{ button_state }}"
                  icon_code: "\uE5DA"
                  button_label: "Reading On/Off"
                  button_bri: >-
                    {% set left_on = is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on') %}
                    {% set right_on = is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on') %}
                    {% set left_raw = state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0) if left_on else 0 %}
                    {% set right_raw = state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0) if right_on else 0 %}
                    {% set left_pct = ((left_raw / 255) * 100) | round(0) | int %}
                    {% set right_pct = ((right_raw / 255) * 100) | round(0) | int %}
                    {% set reading_pct = [left_pct, right_pct] | max %}
                    {% if reading_pct > 0 %}{{ reading_pct }}%{% else %}{% endif %}

          - conditions: "{{ scene_name == 'Dining On/Off' }}"
            sequence:
              - action: script.nspanel_lounge_push_button_state
                data:
                  button_id: button07
                  button_state: "{{ button_state }}"
                  icon_code: "\uEA70"
                  button_label: "Dining On/Off"
                  button_bri: ""

          - conditions: "{{ scene_name == 'All Off' }}"
            sequence:
              - action: script.nspanel_lounge_push_button_state
                data:
                  button_id: button08
                  button_state: "{{ button_state }}"
                  icon_code: "\uE425"
                  button_label: "All Off"
                  button_bri: ""

  #:######################################################################################:#
  # SCRIPT: Refresh All NSPanel Lounge Button States
  #
  # Use this manually after a panel restart, or automatically once at HA start.
  # Normal scene changes do not call this script.
  #:######################################################################################:#
  nspanel_lounge_refresh_all_button_states:
    alias: "NSPanel Lounge - Refresh All Button States"
    mode: restart
    sequence:
      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "Bright"
          button_state: "{{ is_state('switch.nspanel_lounge_scene_bright', 'on') }}"

      - delay:
          milliseconds: 100

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "TV General"
          button_state: "{{ is_state('switch.nspanel_lounge_scene_tv_general', 'on') }}"

      - delay:
          milliseconds: 100

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "Movie"
          button_state: "{{ is_state('switch.nspanel_lounge_scene_movie', 'on') }}"

      - delay:
          milliseconds: 100

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "Balanced"
          button_state: "{{ is_state('switch.nspanel_lounge_scene_balanced', 'on') }}"

      - delay:
          milliseconds: 100

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "Warm Cozy"
          button_state: "{{ is_state('switch.nspanel_lounge_scene_warm_cozy', 'on') }}"

      - delay:
          milliseconds: 100

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "Reading On/Off"
          button_state: "{{ is_state('switch.nspanel_lounge_scene_reading', 'on') }}"

      - delay:
          milliseconds: 100

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "Dining On/Off"
          button_state: "{{ is_state('switch.nspanel_lounge_scene_dining', 'on') }}"

      - delay:
          milliseconds: 100

      - action: script.nspanel_lounge_push_scene_button_state
        data:
          scene_name: "All Off"
          button_state: "{{ is_state('switch.nspanel_lounge_scene_all_off', 'on') }}"

  #:######################################################################################:#
  # SCRIPT: Compatibility Wrapper
  #
  # Older versions used this script name. Keep it as a manual full refresh.
  #:######################################################################################:#
  nspanel_lounge_refresh_button_states:
    alias: "NSPanel Lounge - Refresh Button States"
    mode: restart
    sequence:
      - action: script.nspanel_lounge_refresh_all_button_states

#:########################################################################################:#
# TEMPLATE SWITCHES: NSPANEL BUTTON STATE AND HIGHLIGHTING
#:########################################################################################:#

template:
  - switch:
      ##########################################################################
      # Remembered scenes
      # These switches stay on when input_text.lounge_last_scene matches the
      # last remembered scene name. This allows the NSPanel button to remain
      # highlighted for the selected remembered scene.
      ##########################################################################

      - name: "NSPanel Lounge Scene Bright"
        unique_id: nspanel_lounge_scene_switch_bright
        state: "{{ is_state('input_text.lounge_last_scene', 'Bright') }}"
        turn_on:
          - action: script.lounge_set_scene
            data:
              scene_name: "Bright"
        turn_off:
          - action: script.lounge_set_scene
            data:
              scene_name: "Bright"

      - name: "NSPanel Lounge Scene TV General"
        unique_id: nspanel_lounge_scene_switch_tv_general
        state: "{{ is_state('input_text.lounge_last_scene', 'TV General') }}"
        turn_on:
          - action: script.lounge_set_scene
            data:
              scene_name: "TV General"
        turn_off:
          - action: script.lounge_set_scene
            data:
              scene_name: "TV General"

      - name: "NSPanel Lounge Scene Balanced"
        unique_id: nspanel_lounge_scene_switch_balanced
        state: "{{ is_state('input_text.lounge_last_scene', 'Balanced') }}"
        turn_on:
          - action: script.lounge_set_scene
            data:
              scene_name: "Balanced"
        turn_off:
          - action: script.lounge_set_scene
            data:
              scene_name: "Balanced"

      - name: "NSPanel Lounge Scene Movie"
        unique_id: nspanel_lounge_scene_switch_movie
        state: "{{ is_state('input_text.lounge_last_scene', 'Movie') }}"
        turn_on:
          - action: script.lounge_set_scene
            data:
              scene_name: "Movie"
        turn_off:
          - action: script.lounge_set_scene
            data:
              scene_name: "Movie"

      - name: "NSPanel Lounge Scene Warm Cozy"
        unique_id: nspanel_lounge_scene_switch_warm_cozy
        state: "{{ is_state('input_text.lounge_last_scene', 'Warm Cozy') }}"
        turn_on:
          - action: script.lounge_set_scene
            data:
              scene_name: "Warm Cozy"
        turn_off:
          - action: script.lounge_set_scene
            data:
              scene_name: "Warm Cozy"

      - name: "NSPanel Lounge Scene All Off"
        unique_id: nspanel_lounge_scene_switch_all_off
        state: "{{ is_state('input_text.lounge_last_scene', 'All Off') }}"
        turn_on:
          - action: script.lounge_set_scene
            data:
              scene_name: "All Off"
        turn_off:
          - action: script.lounge_set_scene
            data:
              scene_name: "All Off"

      ##########################################################################
      # Toggle/action scenes
      # These are excluded from input_text.lounge_last_scene, so their displayed
      # state comes from the actual light entities they control.
      ##########################################################################

      - name: "NSPanel Lounge Scene Reading"
        unique_id: nspanel_lounge_scene_switch_reading
        state: >-
          {{
            (
              is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on')
              and (state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0)) > 0
            )
            or
            (
              is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on')
              and (state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0)) > 0
            )
          }}
        turn_on:
          - action: script.lounge_set_scene
            data:
              scene_name: "Reading On/Off"
        turn_off:
          - action: script.lounge_set_scene
            data:
              scene_name: "Reading On/Off"

      - name: "NSPanel Lounge Scene Dining"
        unique_id: nspanel_lounge_scene_switch_dining
        state: >-
          {{
            is_state('light.esp_lounge6chdimmer_dining_table_light', 'on')
            and (state_attr('light.esp_lounge6chdimmer_dining_table_light', 'brightness') | int(0)) > 0
          }}
        turn_on:
          - action: script.lounge_set_scene
            data:
              scene_name: "Dining On/Off"
        turn_off:
          - action: script.lounge_set_scene
            data:
              scene_name: "Dining On/Off"
