#include "vacuum_display.h"
#include <string.h>
static const char font_chars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%-: ";
static const uint8_t font[][5]={{126,9,9,9,126},{127,73,73,73,54},{62,65,65,65,65},{127,65,65,65,62},{127,73,73,73,65},{127,9,9,9,1},{62,65,73,73,121},{127,8,8,8,127},{65,65,127,65,65},{32,64,65,63,1},{127,8,20,34,65},{127,64,64,64,64},{127,2,12,2,127},{127,2,4,8,127},{62,65,65,65,62},{127,9,9,9,6},{62,65,81,33,94},{127,9,25,41,70},{70,73,73,73,49},{1,1,127,1,1},{63,64,64,64,63},{31,32,64,32,31},{127,32,24,32,127},{99,20,8,20,99},{3,4,120,4,3},{97,81,73,69,67},{62,81,73,69,62},{0,66,127,64,0},{66,97,81,73,70},{65,73,73,73,54},{24,20,18,127,16},{79,73,73,73,49},{62,73,73,73,48},{1,113,9,5,3},{54,73,73,73,54},{6,73,73,73,62},{19,11,4,50,49},{8,8,8,8,8},{0,0,54,0,0},{0,0,0,0,0}};
static void text(char *dst,const char *src){size_t i=0;while(i<21u&&src[i]){dst[i]=src[i];++i;}dst[i]=0;}
void vd_render(const vd_input *in,uint8_t frame[512],vd_view *v){
 if(!frame||!v)return;
 memset(frame,0,512);memset(v,0,sizeof(*v));
 if(!in){text(v->lines[0],"INPUT INVALID");text(v->lines[2],"SUCTION --%");}
 else {
  text(v->lines[0],in->fault?"FAULT":in->learning_busy?"CALIBRATING":in->restart_required?"RESTART REQUIRED":in->fan_enabled?"FAN ON":"FAN OFF");
  text(v->lines[1],"LEVEL -");if(in->level>=1&&in->level<=4)v->lines[1][6]=(char)('0'+in->level);
  bool valid=in->qualified&&in->measurement_valid&&in->percent<=100u&&in->fan_enabled&&!in->fault&&!in->learning_busy&&!in->restart_required&&(uint32_t)(in->now_ms-in->sampled_ms)<=500u;
  text(v->lines[2],"SUCTION --%");
  if(valid){
   text(v->lines[2],"SUCTION 000%");v->lines[2][8]=(char)('0'+in->percent/100);
   v->lines[2][9]=(char)('0'+(in->percent/10)%10);v->lines[2][10]=(char)('0'+in->percent%10);
   v->percent_visible=true;v->alarm_visible=in->low_suction;
   text(v->lines[3],in->low_suction?"CHECK FILTER":"SUCTION VALID");
  }else text(v->lines[3],"VALUE UNAVAILABLE");
 }
 for(unsigned page=0;page<4;page++)for(unsigned x=0;x<21&&v->lines[page][x];x++){
  char ch=v->lines[page][x];unsigned f=0;while(font_chars[f]&&font_chars[f]!=ch)++f;
  if(!font_chars[f])continue;
  for(unsigned col=0;col<5;col++)frame[page*128+x*6+col]=font[f][col];
 }
}
bool vd_begin(vd_driver*d,uint8_t addr,const uint8_t f[512]){
 if(!d||!f||(addr!=0x3cu&&addr!=0x3du))return false;
 memset(d,0,sizeof(*d));memcpy(d->frame,f,512);d->address=addr;d->phase=1;return true;
}
bool vd_service(vd_driver*d,vd_write write,void*ctx){
 if(!d||d->phase==0)return false;
 if(!write){d->failed=true;d->phase=0;return false;}
 uint8_t b[17];size_t n=0;
 switch(d->phase){
 case 1:b[0]=0;b[1]=0xae;n=2;break;
 case 2:{const uint8_t init[]={0,0xd5,0x80,0xa8,0x1f,0xd3,0,0x40,0xa1,0xc8,0xda,0x02,0x81,0x7f,0x8d,0x14};memcpy(b,init,sizeof(init));n=sizeof(init);break;}
 case 3:b[0]=0;b[1]=0xa4;b[2]=0xa6;b[3]=0x20;b[4]=0x02;n=5;break;
 case 4:b[0]=0;b[1]=(uint8_t)(0xb0u+d->page);b[2]=0;b[3]=0x10;n=4;break;
 case 5:b[0]=0x40;memcpy(&b[1],&d->frame[d->page*128u+d->chunk*16u],16);n=17;break;
 case 6:b[0]=0;b[1]=0xaf;n=2;break;
 default:d->failed=true;d->phase=0;return false;
 }
 if(!write(ctx,d->address,b,n)){
  uint8_t off[]={0,0xae};d->failed=true;d->phase=0;
  d->display_off_confirmed=write(ctx,d->address,off,sizeof(off));return false;
 }
 if(d->phase==1){d->display_off_confirmed=true;d->phase=2;}
 else if(d->phase==2)d->phase=3;
 else if(d->phase==3)d->phase=4;
 else if(d->phase==4)d->phase=5;
 else if(d->phase==5){if(++d->chunk==8){d->chunk=0;if(++d->page==4)d->phase=6;else d->phase=4;}}
 else {d->display_off_confirmed=false;d->phase=0;}
 return d->phase!=0;
}
