#include <u.h>
#include <libc.h>
#include <bio.h>
#include "dict.h"

/* Possible tags */
enum {
       DF,             /* definition */
       DX,             /* definition/example */
       ET,             /* etymology */
       EX,             /* example */
       LA,             /* label */
       ME,             /* main entry */
       NU,             /* sense number */
       PR,             /* pronunciation */
       PS,             /* grammar part */
       XR,             /* cross reference */
       XX,             /* cross reference (whole entry) */
};

/* Assoc tables must be sorted on first field */

static Assoc tagtab[] = {
       {"df",  DF},
       {"dx",  DX},
       {"et",  ET},
       {"ex",  EX},
       {"la",  LA},
       {"me",  ME},
       {"nu",  NU},
       {"pr",  PR},
       {"ps",  PS},
       {"xr",  XR},
       {"xx",  XX},
};
static long     sget(char *, char *, char **, char **);
static void     soutpiece(char *, char *);

void
slangprintentry(Entry e, int cmd)
{
       char *p, *pe, *vs, *ve;
       long t;

       p = e.start;
       pe = e.end;
       if(cmd == 'h') {
               t = sget(p, pe, &vs, &ve);
               if(t == ME)
                       soutpiece(vs, ve);
               outnl(0);
               return;
       }
       while(p < pe) {
               switch(sget(p, pe, &vs, &ve)) {
               case DF:
                       soutpiece(vs, ve);
                       outchars(".  ");
                       break;
               case DX:
                       soutpiece(vs, ve);
                       outchars(".  ");
                       break;
               case ET:
                       outchars("[");
                       soutpiece(vs, ve);
                       outchars("] ");
                       break;
               case EX:
                       outchars("E.g., ");
                       soutpiece(vs, ve);
                       outchars(".  ");
                       break;
               case LA:
                       outchars("(");
                       soutpiece(vs, ve);
                       outchars(") ");
                       break;
               case ME:
                       outnl(0);
                       soutpiece(vs, ve);
                       outnl(0);
                       break;
               case NU:
                       outnl(2);
                       soutpiece(vs, ve);
                       outchars(".  ");
                       break;
               case PR:
                       outchars("[");
                       soutpiece(vs, ve);
                       outchars("] ");
                       break;
               case PS:
                       outnl(1);
                       soutpiece(vs, ve);
                       outchars(". ");
                       break;
               case XR:
                       outchars("See ");
                       soutpiece(vs, ve);
                       outchars(".  ");
                       break;
               case XX:
                       outchars("See ");
                       soutpiece(vs, ve);
                       outchars(".  ");
                       break;
               default:
                       ve = pe;        /* will end loop */
                       break;
               }
               p = ve;
       }
       outnl(0);
}

long
slangnextoff(long fromoff)
{
       long a;
       char *p;

       a = Bseek(bdict, fromoff, 0);
       if(a < 0)
               return -1;
       for(;;) {
               p = Brdline(bdict, '\n');
               if(!p)
                       break;
               if(p[0] == 'm' && p[1] == 'e' && p[2] == ' ')
                       return (Boffset(bdict)-Blinelen(bdict));
       }
       return -1;
}

void
slangprintkey(void)
{
       Bprint(bout, "No key\n");
}

/*
* Starting from b, find next line beginning with a tag.
* Don't go past e, but assume *e==0.
* Return tag value, or -1 if no more tags before e.
* Set pvb to beginning of value (after tag).
* Set pve to point at newline that ends the value.
*/
static long
sget(char *b, char *e, char **pvb, char **pve)
{
       char *p;
       char buf[3];
       long t, tans;

       buf[2] = 0;
       tans = -1;
       for(p = b;;) {
               if(p[2] == ' ') {
                       buf[0] = p[0];
                       buf[1] = p[1];
                       t = lookassoc(tagtab, asize(tagtab), buf);
                       if(t < 0) {
                               if(debug)
                                       err("tag %s\n", buf);
                               p += 3;
                       } else {
                               if(tans < 0) {
                                       p += 3;
                                       tans = t;
                                       *pvb = p;
                               } else {
                                       *pve = p;
                                       break;
                               }
                       }
               }
               p = strchr(p, '\n');
               if(!p || ++p >= e) {
                       if(tans >= 0)
                               *pve = e-1;
                       break;
               }
       }
       return tans;
}

static void
soutpiece(char *b, char *e)
{
       int c, lastc;

       lastc = 0;
       while(b < e) {
               c = *b++;
               if(c == '\n')
                       c = ' ';
               if(!(c == ' ' && lastc == ' ') && c != '@')
                       outchar(c);
               lastc = c;
       }
}