//
// DigitalClockView.m
// rev 1.1
//
// Matt Pharr- pharr@cs.yale.edu
// NeXTMail welcome
//

#import "DigitalClockView.h"
#import <appkit/graphics.h>
#import <libc.h>
#import <dpsclient/wraps.h>
#import <time.h>
#import <strings.h>
#import <appkit/NXImage.h>
#import <appkit/Font.h>
#import <appkit/publicWraps.h>


@implementation DigitalClockView

- fixPosition
{
  if (currentLocation.x + currentSize.width >= bounds.size.width)
    currentLocation.x = bounds.size.width - currentSize.width;
  if (currentLocation.x <= bounds.origin.x)
    currentLocation.x = 0;

  if (currentLocation.y + currentSize.height >= bounds.size.height)
    currentLocation.y = bounds.size.height - currentSize.height;
  if (currentLocation.y <= bounds.origin.y)
    currentLocation.y = 0;

  return self;
}


- bounceIfNeeded
{
  if (currentLocation.x <= bounds.origin.x)  // keep it ON the screen
    moveVector.x= randBetween(0.5, 1.5);
  if (currentLocation.x + currentSize.width >= bounds.size.width)
    moveVector.x= (-1) * randBetween(0.5, 1.5);

  if (currentLocation.y <= bounds.origin.y)
    moveVector.y= randBetween(0.5, 1.5);
  if (currentLocation.y + currentSize.height >= bounds.size.height)
    moveVector.y= (-1) * randBetween(0.5, 1.5);

  return self;
}


- chooseColor
{
  float dr, dg, db;

  if ([Window defaultDepthLimit] == NX_TwoBitGrayDepth) {
     currGrey= 1.0;          // boring city...
     PSsetgray(currGrey);
  }

  else {
     dr= randBetween(-.1, .1);   // randomly move the red, green, and blue
     dg= randBetween(-.1, .1);   // components of the color around between
     db= randBetween(-.1, .1);   // 0 and 1. There is a minor bummer in that
                                 // you only see the effect of the color
                                 // change once a second, because it only
                                 // draws the time into the bitmap when the
                                 // time changes. Would be an easy modification
                                 // to get it to redraw the bitmap more
                                 // frequently, but its probably not worth
                                 // the trouble. Depending on how this ends
                                 // up looking in color (wish I knew!), it
                                 // might be better to replace everything
                                 // between the else and the PSsetrgbcolor
                                 // with just a PSsetrgbcolor(), with constant
                                 // arguments...

     currR += dr;    currG += dg;     currB += db;

     if (currR < 0.0) currR= 0.0;
     if (currR > 1.0) currR= 1.0;
     if (currG < 0.0) currG= 0.0;
     if (currG > 1.0) currG= 1.0;
     if (currB < 0.0) currB= 0.0;
     if (currB > 1.0) currB= 1.0;
     PSsetrgbcolor(currR, currG, currB);
  }

  return self;
}


- oneStep
{
  time_t tTime;
  struct tm *currentTime;

  currentLocation.x += moveVector.x;       // move the x and y positions of the image
  currentLocation.y += moveVector.y;       // as indicated by the move vectors
  [self bounceIfNeeded];
  [self fixPosition];

  time(&tTime);
  currentTime= localtime(&tTime);
  strftime(theTime, 10, "%H:%M:%S", currentTime);

  if (strcmp(theTime, lastTime) != 0) {   // if the time has changed...
    strcpy(lastTime, theTime);

    currentLocation.x += moveVector.x;   // move it one more time so it's not so jerky
    currentLocation.y += moveVector.y;   // when the time changes...
    [self bounceIfNeeded];
    [self fixPosition];

    if ([currentImage lockFocus] == YES) {
      PSsetgray(0.0);
      PSrectfill(0, 0, currentSize.width, currentSize.height);
      [theFont set];

      PSsetgray(.333);                     // give it a little shadow
      PSmoveto(14, 136);
      PSshow(theTime);

      PSmoveto(10.0, 138.0);
      [self chooseColor];
      PSshow(theTime);            // to be really fancy, it would be good to fix the
                                  // kerning on 1's by hand, so the next number was
                                  // printed closer, but this is pretty minor...
                                  // Some people have also expressed an interest in
                                  // non-military time, and AM/PM instead. If BackSpace
                                  // ever gives me a view to work with to let the user
                                  // configure the modules, this will be an option.

      [currentImage unlockFocus];
    }
  }

  [currentImage composite:NX_COPY toPoint:&currentLocation];

  usleep((1*1000000)/68);					// sleep a few vblanks

  return self;
}


- (const char *)windowTitle
{
  return "Digital Clock";
}


- drawSelf:(const NXRect *)rects :(int)rectCount
{
  if (!rects || !rectCount) {
    return self;
  }

  PSsetgray(0);
  NXRectFill(rects);

  return self;
}


- initFrame:(const NXRect *)frameRect
{
  [super initFrame:frameRect];

  currentLocation.x= 400.0;
  currentLocation.y= 400.0;

  moveVector.x= randBetween(0.5, 1.5);
  moveVector.y= randBetween(0.5, 1.5);

  *theTime= '\0';
  *lastTime= '\0';

  theFont=  [Font newFont:"Times-Roman" size:180.0];

  currGrey= currR= currG= currB= .5;

  currentSize.width= [theFont getWidthOf:"88:88:88"] + 17.0;  // keep the bitmap a 
  currentSize.height= 180.0;                                  // little on the big size,
                                                              // so there is extra black
                                                              // around the edges, so that
                                                              // the previous drawing
                                                              // is automagically erased.

  currentImage= [[NXImage alloc] initSize:&currentSize];
  [currentImage setFlipped:YES];

  return self;
}

@end
