#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>

struct termios told, tnew;
int tw = 0, th = 0, cw = 0, ch = 0;

static int
echo_off(void)
{
   if (tcgetattr(0, &told) != 0) return -1;
   tnew = told;
   tnew.c_iflag &= ~(
                     IGNBRK |
                     BRKINT |
                     IGNPAR |
                     PARMRK |
                     INPCK |
                     ISTRIP |
                     INLCR |
                     IGNCR |
                     ICRNL |
                     IXON |
                     IXANY |
                     IXOFF
                    );
   tnew.c_oflag &= ~(
                     OPOST |
                     ONLCR |
                     OCRNL |
                     ONOCR |
                     ONLRET |
                     OFILL |
                     OFDEL
/*
                     NLDLY |
                     CRDLY |
                     TABDLY |
                     BSDLY |
                     VTDLY
 */
                    );
   tnew.c_lflag &= ~(
                     ISIG |
                     ICANON |
                     ECHO |
                     ECHOE |
                     ECHOK |
                     ECHONL |
                     NOFLSH |
                     IEXTEN
                     );
   if (tcsetattr(0, TCSAFLUSH, &tnew) != 0) return -1;
   return 0;
}

static int
echo_on(void)
{
   return tcsetattr(0, TCSAFLUSH, &told);
}



static void
begin(const char *path, const char *group, const char *chid,
      char ch, int w, int h)
{
   char buf[4096];

   snprintf(buf, sizeof(buf),
            "%c}ij%c%i;%i;%s\n%s\nchid\n%s"
            , 0x1b, ch, w, h, path, group, chid);
   if (write(0, buf, strlen(buf) + 1) < 0) perror("write");
}

int
countcpu(void)
{
   FILE *f;
   char buf[1024];
   int i = 0;
   
   f = fopen("/proc/stat", "r");
   if (!f) return -1;
   fgets(buf, sizeof(buf), f);
   while (fgets(buf, sizeof(buf), f))
     {
        if (!strncmp(buf, "cpu", 3)) i++;
     }
   fclose(f);
   return i;
}

static void
cleanup(void)
{
   echo_on();
   exit(0);
}

static void
sigint(int v)
{
   cleanup();
}

static void
sigquit(int v)
{
   cleanup();
}

int
main(int argc, char **argv)
{
   char buf[1024], wd[1024], buf2[1024], x, y, w, h;
   int i, n;
   unsigned long *v, *vs;
   int id1, id2;

   if (!getenv("TERMINOLOGY")) return 0;
   signal(SIGINT, sigint);
   signal(SIGQUIT, sigquit);
   id1 = getpid();
   id2 = time(NULL);

   echo_off();
   snprintf(buf, sizeof(buf), "%c}qs", 0x1b);
   if (write(0, buf, strlen(buf) + 1) < 0) perror("write");
   if (scanf("%i;%i;%i;%i", &tw, &th, &cw, &ch) != 4)
     {
        echo_on();
        return 0;
     }
   if ((tw <= 0) || (th <= 0) || (cw <= 1) || (ch <= 1))
     {
        echo_on();
        return 0;
     }
   n = countcpu();
   w = (tw - 10) / n;
   h = w / 2;
   if (!getcwd(wd, sizeof(wd))) exit(1);
   snprintf(buf2, sizeof(buf2), "%s/cpufreq.edj", wd);
   for (i = 0; i < n; i++)
     {
        snprintf(buf, sizeof(buf), "cpu%i.%i.%i", id1, id2, i);
        begin(buf2, "dial", buf, 'a' + i, w, h);
     }
   for (y = 0; y < h; y++)
     {
        strcpy(buf, "\033}ib");
        write(0, buf, strlen(buf) + 1);
        for (i = 0; i < n; i++)
          {
             for (x = 0; x < w; x++)
               {
                  buf[(i * w) + x] = 'a' + i;
                  buf[(i * w) + x + 1] = 0;
               }
          }
        write(0, buf, strlen(buf));
        strcpy(buf, "\033}ie");
        write(0, buf, strlen(buf) + 1);
        write(0, "\r\n", 2);
     }
   v = calloc(n, sizeof(unsigned long));
   vs = calloc(n, sizeof(unsigned long));
   for (;;)
     {
        FILE *f;

        f = fopen("/proc/stat", "r");
        if (f)
          {
             fgets(buf, sizeof(buf), f);
             for (i = 0; i < n; i++)
               {
                  unsigned long v1 = 0, v2 = 0, v3 = 0, v4 = 0;
                  unsigned long vv, vsum;
                  int cpu;
                  char nbuf[1000];

                  fgets(buf, sizeof(buf), f);
                  sscanf(buf, "%*s %lu %lu %lu %lu", &v1, &v2, &v3, &v4);
                  vv = v1 + v2 + v3 - v[i];
                  vsum = v1 + v2 + v3 + v4 - vs[i];
                  v[i] = v1 + v2 + v3;
                  vs[i] = v1 + v2 + v3 + v4;
                  if (vsum > 0)
                    cpu = (100 * vv) / vsum;
                  else
                    cpu = 0;
                  snprintf(nbuf, sizeof(nbuf), "cpu%i.%i.%i", id1, id2, i);
                  snprintf(buf, sizeof(buf),
                           "%c}iC%s\nmessage\n3\nint_set\n1\n%i",
                           0x1b, nbuf, cpu);
                  write(0, buf, strlen(buf) + 1);
               }
             fclose(f);
          }
        usleep(500 * 1000);
     }
   echo_on();
   return 0;
}
