/* ----------------------------------------------------------------------

   PWS16LBL written by L. Granroth
            modified and additional code by R.Baines  7/89

   This module places ALL labels for Normal plots on the graphics screen.

   ---------------------------------------------------------------------- */


#include <graphics.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "pwstruct.h"
#include "pwsglobl.h"
#include "pwsgraph.h"
#include "proto.h"


/* Internal Functions */
void compute_tics(void);
void display_top_labels(void);
void display_side_labels(void);
void display_time_labels(void);
void display_bottom_labels(void);

/* Internal Global Var */
char string[LLEN];

/*---------------------------------------------------------------------

  pws16_label written by L. Granroth  09-02-88
              modified by R. Baines   07-26-89
  to produce plot labels for the PWS16PC program.

  ---------------------------------------------------------------------*/

void pws16_label (void)
{

  /* settings for rgb values to create grays going from black to white */
  unsigned char grays[]=
  { 0, 5, 8, 11, 14, 17, 20, 24, 28, 32, 36, 40, 45, 50, 56, 63 };
  unsigned char reds[]=
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 23, 33, 43, 53, 63, 63 };
  unsigned char greens[]=
  { 0, 0, 0, 0, 23, 33, 43, 53, 63, 53, 43, 33, 23, 13, 0, 63 };
  unsigned char blues[]=
  { 0, 23, 43, 63, 53, 43, 33, 13, 0, 0, 0, 0, 0, 0, 0, 63 };

  /* table of frequencies to compute fg */
  float logfreq[] =
  { 0.0,
    1.000,1.250,1.493,1.750,2.000,2.250,2.493,2.750,
    3.000,3.250,3.493,3.750,4.000,4.250,4.493,4.750
  };

  float freqlr;
  int i;

  /* -------------------- pws16_label -------------------- */

  /* Set up Graphics Screen */
  initgraph (&GraphDriver, &GraphMode, BGI_Path);
  testGraphError();

  /* Get values based off graphics mode and driver used */
  MaxX = getmaxx();
  MaxY = getmaxy();
  MaxColor = getmaxcolor();

  if (Bcolor != getbkcolor()) {
     cleardevice();
     setbkcolor(Bcolor);
  }

  /* set font */
  settextstyle(Font, HORIZ_DIR, USER_CHAR_SIZE);
  testGraphError();

  /* Init variables for later processing */

  Tscale = (float) (NumWide+2) / Cmd.span;

  /* Setup up depending on whether shading or not */
  if (Shade) {
     if (Pastel)
        /* Set colors */
        for (i = 0; i < NUM_CHAN; i++)
	{
	   setrgbpalette (i, reds[i], greens[i], blues[i]);
	   setpalette (i, i);
	}
     else
        /* Set grays */
        for (i=0; i < NUM_CHAN; i++)
	{
           setrgbpalette(i, grays[i], grays[i], grays[i]);
           setpalette(i, i);
        }

     if (Cmd.nchan == 1)
       Zmul = NumHigh;
     else {
       Zmul = (NumHigh)/(Cmd.nchan-1);
       NumHigh = Zmul*(Cmd.nchan-1);       /* force integral number of pixels */
     }

     Zdiv = (Zmax==Zmin) ? 1 : abs(Zmax-Zmin);
     Zscale = (float) Zmul / (float) Zdiv;

     /* Set Range of Colors */
     for (i=0; i < NUM_CHAN; i++)
       Range[i] = Zmin + Zdiv/NUM_CHAN*i;
  }
  else {
     if (!ColorsSet) {
	Lcolor = MaxColor;     /* set everything to white for now */
	Pcolor = MaxColor;
	Gcolor = MaxColor;
	Acolor = (MaxColor>2) ? MaxColor/2 : MaxColor;
     }

     setcolor(Lcolor);
     Zmul = NumHigh / Cmd.nchan;
     NumHigh = Zmul * Cmd.nchan;        /* force integral number of pixels */
     Zdiv = (Zmax==Zmin) ? 1 : abs(Zmax-Zmin);
     Zscale = (float) Zmul / Zdiv;

     f0 = logfreq[Cmin];
     freqlr = (float) abs((logfreq[Cmd.chan[Cmd.nchan-1]] - f0)*100)/100;
     Fscale = (freqlr != 0) ? ceil( (NumHigh-Zmul) / freqlr * 100) /100 : 1;

     /* compute placement of vertical tics */
     compute_tics();
  }

    /* draw box */
  if (Shade)
     rectangle (Xorg-1, Yorg-NumHigh-1, Xorg+NumWide, Yorg+1);
  else
     rectangle (Xorg-1, Yorg-NumHigh, Xorg+NumWide, Yorg+1);

    /* insert frequency, channel, and time labels and heading here */
  display_top_labels();
  display_side_labels();
  display_time_labels();
  display_bottom_labels();

} /* pws16_label */


/* ---------------------------------------------------------------------

   Compute_Tics by R. Baines 07-26-89
   insert check for number of channels to determine the use of
   decade or full logarithmic tics here

   --------------------------------------------------------------------- */

void compute_tics (void)
{
  int i, k, j, i1, i2, i3, z;
  double delta, a;

  k = 0;
  if (Cmd.nchan > 4)
  {
    if (Cmd.units > 1)
    {
      i1 = Zmin;
      i2 = Zmax;
      i3 = (i2-i1)/6000+1000;
    }
    else
    {
      i1 = Zmin;
      i2 = Zmax;
      i3 = ((i2-i1) <= 100) ? 10 : 50;
    }
    for (i=i1; i<i2; i+=i3)
    {
      z = (i-Zmin)*Zscale;
      if ((z > 0) && (z < Zmul))
        Ztic[k++] = z;
    }
  }
     /* insert logarithmic tic code here */
  else /* less than 4 channels to be plotted */
  {
    if (Cmd.units > 1)
    {
      i1 = Zmin/1000-1;
      i2 = Zmax/1000;
      for (i=i1; i<=i2; i++)
      {
        if (k == 63)  break;
        delta = pow10(i);
        a = 0;
        for (j=1; j<10; j++)
        {
          a += delta;
          z = (log10(a)*1000-Zmin)*Zscale;
          if (((z > 0) && (z < Zmul)) && ((k < 63) && (Ztic[k-1] != z)))
            Ztic[k++] = z;
        }
      }
    }
    else /* uncalibrated */
    {
      i1 = Zmin;
      i2 = Zmax;
      for (i=i1; i<=i2; i+=10)
      {
        z = (i-Zmin)*Zscale;
        if ((z > 0) && (z < Zmul))
          Ztic[k++] = z;
      }
    }
  }
    Ztic[k] = -1;
}

/* ---------------------------------------------------------------------

   display_top_labels by R. Baines 07-26-89

   --------------------------------------------------------------------- */

void display_top_labels(void)
{
  /* Table of different Units */
  static char *units[] =
  { "  UNCALIBRATED",
    "       LOG (V)",
    "    LOG (Vrms)",
    "     LOG (V/M)",
    "  LOG (Vrms/M)",
    "LOG (V^2^/M^2^/Hz)",
    " LOG (W/M^2^/Hz)"
  };

  int lyr, ldoy, lhr, lmn;
  float lsec;
  double tbeg, tend;

    /* Report which Voyager */

  sprintf (string,"VOYAGER-%i PWS ", Cmd.spacecraft);
  settextjustify (LEFT_TEXT, BOTTOM_TEXT);

  Xmul = NumWide * Percent40;
  Ymul = Yorg - NumHigh;
  setusercharsize(Xmul, textwidth(string), Ymul, textheight(string));

  moveto(Xorg, Ymul-LongTic-1);   /* -1 is size of lines in rectangle */
  outtext(string);

    /* Xpos stores x-asis position, where next two labels are to appear */
  Xpos = getx();
  Ypos = gety();

    /* Report Bottom Heading informing range of data and unit type */
  if (Cmd.units == 1)
     sprintf(string, "MIN  % 3.1f  MAX  % 3.1f      ", Zmin, Zmax);
  else
     sprintf(string, "MIN  % 3.1f  MAX  % 3.1f      ", Zmin/1000, Zmax/1000);

  settextjustify (LEFT_TEXT, TOP_TEXT);
  setusercharsize(1,1,1,1);
  Ymul = Xmul = (MaxY-Yorg-LongTic)/3;;
  Xdiv = Ydiv = textheight(string);
  setusercharsize(Xmul, Xdiv, Ymul, Ydiv);

  Ypos = Yorg-NumHigh-Ydiv-2*LongTic;
  moveto(Xpos, Ypos);
  outtext(string);
  superscript(Xmul, Xdiv, Ymul, Ydiv, units[Cmd.units-1]);

    /* Get value of current dates plus the span to tell when span ends */

  tbeg = time2sec(Cmd.year, Cmd.day, Cmd.hour, Cmd.minute, Cmd.millisec*1000);
  tend = tbeg + (double) Cmd.span;
  sec2time(tend, &lyr, &ldoy, &lhr, &lmn, &lsec);

    /* Report Span of Data from current year-day-hour to year-day-hour */

  sprintf(string, "BEGIN %02d %003d %02d%02d  END %02d %003d %02d%02d  SCET",
          Cmd.year, Cmd.day, Cmd.hour, Cmd.minute, lyr, ldoy, lhr, lmn);

  outtextxy(Xpos, Ypos-Ydiv-LongTic-LongTic, string);
}

/* ---------------------------------------------------------------------

   display_side_labels by R. Baines 07-26-89

   --------------------------------------------------------------------- */

void display_side_labels(void)
{

   /* Frequencies for each channel */
   char *freq[] =
   { "10.0 ","17.8 ","31.1 ","56.2 ",
     "100. ","178. ","311. ","562. ",
     "1.00","1.78","3.11","5.62",
     "10.0","17.8","31.1","56.2"
   };
   int i, Xpos2, mul, div;

   /* Set Font Size */

   if (Shade)
      settextjustify (LEFT_TEXT, CENTER_TEXT);
   else
      settextjustify (LEFT_TEXT, BOTTOM_TEXT);
   setusercharsize(1,1,1,1);
   mul = (MaxY-Yorg-LongTic)/3;;
   div = textheight("0");
   setusercharsize(mul, div, mul, div);

   Ypos = Yorg-Tic;
   Xpos = MaxX-textwidth("00");
   Xpos2 = textwidth("00.0");

   for (i=0; i<Cmd.nchan; i++)
   {
       /* If 'k' req'd then output separately so k's line up */
      if (Cmd.chan[i]>8)
	 outtextxy(Xpos2, Ypos,"k");
      outtextxy(0, Ypos, freq[Cmd.chan[i]-1]);
      sprintf(string, "%2d", Cmd.chan[i]);
      outtextxy(Xpos, Ypos, string);
      Ypos-=Zmul;
   }
}

/* ---------------------------------------------------------------------

   display_time_labels by R. Baines 07-26-89

   --------------------------------------------------------------------- */

void display_time_labels(void)
{
  int th, td, day, label, labtic, jhr, jmn, jstep, daymul, days_year, mul, div;
  long int ttic, tstep;

  /* Init vars used in computing placement of time-labels */
  days_year = (Cmd.year%4) ? YEAR_DAYS : LEAP_YEAR_DAYS;

    /* time before midnight of first day of plot is calculated in th and td*/
  th = (-1) * Cmd.minute * MIN_SEC;
  td = th - Cmd.hour * HOUR_SEC;
    /* day of the year - starting with previous day */
  day = Cmd.day - 1;

    /* Set char size depending on resolution */

  settextjustify (CENTER_TEXT, TOP_TEXT);
  setusercharsize(1,1,1,1);
  mul = (MaxY-Yorg-LongTic)/3;
  div = Ydiv;
  setusercharsize(mul, div, mul, div);

    /* Draw Tics on Side Lines */
  Ypos = Yorg+1;
  line(Xorg-1, Ypos, Xorg-1, Ypos+LongTic);
  line(Xorg+NumWide, Ypos, Xorg+NumWide, Ypos+LongTic);

    /* Place tics at daily intervals */

     /* daymul used to space out tics per x # of days */
  daymul = (int) (Cmd.span/(8*DAY_SEC)) + 1;

    /* time of day labels; if span > 4 days  */
  if (Cmd.span > DAY_SEC*4)
  {
       /* if span > one week step each 12 hours else each 4 hours  */
     tstep = (Cmd.span > WEEK_SEC) ? HALF_DAY_SEC : HOUR_SEC*4;

       /* Plot hourly tics spaced out as define by tstep*/
     ttic=td;
     while (ttic < 0)
        ttic += tstep;

     while (ttic <= Cmd.span)
     {
       Xpos = Xorg - 1 + NINT(ttic * Tscale);
       if (Xpos > Xorg+NumWide)
         Xpos = Xorg+NumWide;

       moveto(Xpos, Ypos);
       if (ttic % DAY_SEC)      /* label if day passed => ELSE statement */
         lineto(Xpos, Ypos+Tic);
       else
       {
          lineto(Xpos, Ypos+LongTic);

            /* increment day and reset day if neccessary */
          day = (day==days_year) ? 1 : day+1;
          if (day%daymul==0)
          {
            sprintf(string, "%2d", day);
            outtextxy(Xpos, Ypos+LongTic, string);
          }
       }
       ttic += tstep;
     }
  }

    /* if span between 4 days and 12 hours */
  else if (Cmd.span > HALF_DAY_SEC)
  {
      /* if span > 24 hours  set labtic to 2 else 1 */
    labtic = (Cmd.span > DAY_SEC) ? 2 : 1;
    label = 2*labtic;

    /* Plot hourly tics */

    /* initialize hour label */
    jhr = (Cmd.hour==0) ? 24 : Cmd.hour;

    /* set ttic to # hours prior midnight (nonzero if begin not midnight) */
    ttic=th;
    while (ttic < 0)
       ttic += tstep;

    while (ttic <= Cmd.span)
    {
       if ((jhr%labtic)==0)       /* if at spot to write tic */
       {
         Xpos = Xorg - 1 + NINT(ttic * Tscale);
         if (Xpos > Xorg+NumWide)
            Xpos = Xorg+NumWide;

         moveto(Xpos, Ypos);
         if (jhr%label)
           lineto(Xpos, Ypos+Tic);
         else
         {
           lineto(Xpos, Ypos+LongTic);
           sprintf(string, "%02d", (jhr==24) ? 0 : jhr);
           outtextxy(Xpos, Ypos+LongTic, string);
         }
       }
     jhr = (jhr < 24) ? jhr+1 : 1;
     ttic += HOUR_SEC;                  /* step by hour */
    }
  }
  else                       /* else span <= 12 hours */
  {
    if (Cmd.span > HOUR_SEC*6)      /* if span > 3 */
    {
        /* set tstep according to span greater or less than six hours */
      tstep = 600;
      label = 60;
    }
    else if (Cmd.span > HOUR_SEC)
    {
      /* if span <= 6 days and > one hour */
      tstep = 300;
      label = (Cmd.span > HOUR_SEC*3) ? 30 : 15;
    }
    else
    {
        /* if span <= one hour */
      tstep=60;
      label = (Cmd.span > HOUR_SEC/2 ) ? 10 : 5;
    }

    /* plot tics on hours and minutes */
    jhr = Cmd.hour;
    jmn = 0;
    ttic = th;
    jstep = NINT(tstep/MIN_SEC);
    while (ttic <= Cmd.span)
    {
      if (ttic >= 0)
      {
        Xpos = Xorg - 1 + NINT(ttic*Tscale);
        if (Xpos > Xorg+NumWide)
          Xpos = Xorg+NumWide;

        moveto(Xpos, Ypos);

          /* if at position to write text and tic */
        if (jmn%label)
          lineto(Xpos, Ypos+Tic);
        else
        {
          lineto(Xpos, Ypos+LongTic);
          sprintf(string, "%04d", jhr*100+jmn);
          outtextxy(Xpos, Ypos+LongTic, string);
        }
      }
      ttic+=tstep;
      jmn +=jstep;
      if (jmn >= HOUR_MIN)
      {
        jmn = 0;
        jhr++;
      }
      if (jhr>=24)
        jhr = 0;
    }
  }
}

/* ---------------------------------------------------------------------

   display_bottom_labels by R. Baines 07-26-89

   --------------------------------------------------------------------- */

void display_bottom_labels(void)
{
  time_t the_time;
  struct tm *ptr; /* time pointer */
  int mul, div;

    /* display SCET */
  strcpy(string, "SCET ");
  settextjustify (LEFT_TEXT, TOP_TEXT);
  outtextxy(0, gety(), string);

    /* display command line on left of bottom line */
  settextjustify (LEFT_TEXT, BOTTOM_TEXT);
  setusercharsize(1,1,1,1);
  mul = (MaxY - Yorg - LongTic)/3.5;
  div = textheight(string);
  setusercharsize(mul, div, mul, div);

  strcpy(string, Cmdline);
  while (textwidth(string) > NumWide)
    string[strlen(string)-1] = '\0';

  outtextxy(0, MaxY, string);

  /* display current date at right of bottom line */
  settextjustify (RIGHT_TEXT, BOTTOM_TEXT);
  time(&the_time);
  ptr = localtime(&the_time);
  sprintf(string,"[%02d-%02d-%02d]", ptr->tm_mon+1, ptr->tm_mday, ptr->tm_year);
  outtextxy(MaxX, MaxY, string);
}
