#include "vacuum_panel_runtime.h"
#include <string.h>
void vpr_init(vpr_state *s){
 if(!s)return;
 memset(s,0,sizeof(*s));pk_init(&s->keys);vui_init(&s->ui);s->output.level=1;
}
vpr_output vpr_step(vpr_state *s,uint16_t raw,bool adc_valid,bool power,
                   bool fault,bool busy,bool ready,uint32_t now){
 vpr_output o={0};if(!s)return o;
 bool gap=s->have_sample&&(uint32_t)(now-s->last_ms)>100u;
 if(gap||!adc_valid||pk_classify(raw)==PK_INVALID){
  uint8_t level=s->ui.level;
  vpr_init(s);s->ui.level=level;s->output.level=level;
 }
 if(!s->have_sample||power!=s->power_candidate){s->power_candidate=power;s->power_since=now;}
 s->have_sample=true;s->last_ms=now;
 if(!adc_valid||pk_classify(raw)==PK_INVALID){o.ui=s->output;return o;}
 pk_output k=pk_step(&s->keys,raw,true,now);
 o.key=k.key;
 /* During a valid transition retain the last UI request, but faults stop it
    immediately even while another key is bouncing. Never replay learning pulses. */
 s->output.learning_request=false;
 if(fault||busy){
  s->ui.run_requested=false;s->ui.hold_active=false;s->ui.hold_consumed=true;
  s->output.run_requested=false;
  /* Prime held states so fault withdrawal cannot create a press edge. */
  s->ui.previous_power=power;s->ui.previous_plus=k.plus;s->ui.previous_minus=k.minus;
 }
 if(k.valid&&(uint32_t)(now-s->power_since)>=20u){
  vui_input in={power,k.plus,k.minus,fault,busy,ready};
  s->output=vui_step(&s->ui,&in,now);o.keys_valid=true;
 }
 o.ui=s->output;return o;
}
