#include "mmix.h"

short maxx,maxy;  /* screenmaxima */

static void draw_hline(int i, char *ch); /* draw an hline */
static void draw_box(int x1, int y1, int x2, int y2); /* draw a box */
static void draw_init(void);

static unsigned char *draw_buf;    /* some textbuf for the terminal */
static unsigned draw_len; /* the len of this textbuf */

static void draw_hline(int i, char *ch) {
 if (i<0) return;
 while (i!=1) { draw(ch);--i; }
 return;
}

static void draw_box(int x1, int y1, int x2, int y2) {
 register int i;
 gotoxy(x1,y1);draw(AC_TL);draw_hline(x2-x1,AC_HL);draw(AC_TR);
 for (i=1;i!=y2-1;++i) {
  gotoxy(x1,y1+i);draw(AC_VL);
  gotoxy(x2,y1+i);draw(AC_VL);
 }
 gotoxy(x1,y2);draw(AC_BL);draw_hline(x2-x1,AC_HL);draw(AC_BR);
 return;
}

static void draw_init(void) {
 draw(C_NORMAL T_CLEAR C_BOX); /* the bigbox */
 draw_box(1,1,maxx,maxy);

 gotoxyw(1,6, AC_ML); draw_hline(maxx-1,AC_HL); draw(AC_MR);

 draw(C_VERSION);
 gotoxyw(3,2, "mmix version " VERSION);
 draw(C_DESCRIPT);
 gotoxyw(3,4, "mixer: ");
 gotoxyw(3,5, "config:");
 return;
}

void draw_exit(const unsigned char *msg, int i) {
 draw(T_QUIT); draw(msg);
 tty_mode_restore();
 exit(i);
}

/* fill buffer with *msg, if full, then flush it */
void draw_str(const unsigned char *msg) {
 if (!msg || str_len(msg)<=0) return;
 draw_buf=str_add(&draw_buf, msg);
 draw_len=str_len(draw_buf);
 if (draw_len>DRAW_BUFSIZE) draw_flush();
}

/* flush the buffer */
void draw_flush(void) {
 if (draw_len>0) {
  write(1, draw_buf, draw_len);
  mem_set(draw_buf, 0, draw_len+1);
  xfree(draw_buf);
 }
 draw_buf=0; draw_len=0;
}

void draw_update(struct mmix *m) {

 if isset(U_ALL) {
  draw(C_NORMAL T_CLEAR);
  tty_getsize(&maxx,&maxy);
  draw_init();
  unset(U_ALL);
  set(U_MIXVOL|U_MIXDEV|U_MIXRES|U_MIXCFG);
 }

 if isset(U_MIXRES) { /* resource of device changed */
  r_res=mixer_realres(&m[0], c_res);
  unset(U_MIXRES);
  set(U_MIXVOL);
 }

 if isset(U_MIXCFG) { /* configuration changed */
  gotoxyw(11, 5, C_NORMAL); draw_hline(maxx-11," ");
  gotoxy(11, 5); draw(C_STATUS "%s", m->cname[c_cfg]);
  gotoxy(maxx-str_len((unsigned char*)mmix_config)-1, 5); draw("%s", mmix_config);
  unset(U_MIXCFG);
  set(U_MIXVOL|U_MIXDEV);
 }


 if isset(U_MIXDEV) { /* device changed */
  gotoxyw(11, 4, C_NORMAL); draw_hline(maxx-11," ");
  gotoxy(11, 4); draw(C_STATUS "%s", m->mname);
  gotoxy(maxx-str_len((unsigned char*)m->fname)-1, 4); draw("%s", m->fname);
  unset(U_MIXDEV);
  set(U_MIXVOL);
 }

 if isset(U_MIXVOL) { /* volume changed */
  draw(C_STATUS);
  draw_update_mixvol(&m[0]);
  unset(U_MIXVOL);
 }

 if (draw_len) draw_flush();
 return;
}

void draw_update_mixvol(struct mmix *m) {
 register int li,c; /* li==line, c==device */
 char *mono;
 int namemax=0;

 /* find longest resource name */
 for (c=0;c<SOUND_MIXER_NRDEVICES;c++)
  if (str_len((unsigned char*)m->rname[c])>namemax) {
   namemax=str_len((const unsigned char *)m->rname[c]);
  }
 draw(C_NORMAL); /* normal color is std... */
 mono=mallocn(char, 4); /* mono/stereo is a bit ugly :( */

 /* now, for all devs */
 for (li=c=0;c<SOUND_MIXER_NRDEVICES;c++)
 if ((m->devmask&(1<<c)) == (1<<c)) {
  li++;

  if (c==r_res) { draw(T_BOLD); } else { draw(C_NORMAL); }

  /* mono/stereo */
  if (m->v[0][c].s==R_ON) { xsprintf(mono, "%3d", m->v[0][c].right); }
  else { xsprintf(mono, "%s", "   "); /* mono */ }

  gotoxy(3,6+li); draw("%s ", m->rname[c]);
  gotoxy(4+namemax,6+li);
  draw("%s[%-3d%s", m->v[0][c].m==R_ON?C_MUTED:C_NORMAL, m->v[0][c].left, VOL_BL);

  draw_hline(maxx-(namemax+18), VOL_HL);
  {
   int x1=namemax+9,x2=maxx-11;
   int _l,_m,_r;
   if (m->v[0][c].s==R_OFF) { /* mono -> only _m */
    _m=(int)(((float)(x2-x1)/100)*m->v[0][c].left);
    gotoxyw(x1+_m, 6+li, VOL_M);
   } else { /* stereo */
    _r=(int)(((float)(x2-x1)/100)*m->v[0][c].right);
    _l=(int)(((float)(x2-x1)/100)*m->v[0][c].left);
    _m=(int)(((float)(x2-x1)/100)*((m->v[0][c].left+m->v[0][c].right)/2));
    gotoxyw(x1+_l, 6+li, VOL_L);
    gotoxyw(x1+_r, 6+li, VOL_R);
    gotoxyw(x1+_m, 6+li, VOL_M);
   }
  }
  gotoxy(maxx-10,6+li);
  draw("%s%s]%s", VOL_BR, mono, C_NORMAL);
  gotoxy(maxx-5, 6+li);
  draw(" %s", m->v[0][c].r==R_NO?"":m->v[0][c].r==R_ON?"[R]":"[ ]");

 } /* devmask */
 xfree(mono);
} /* end of function */
