/*
  Analogue Clock Local Time X11 Desktop Application in C++
  RJM Programming
  September, 2019
  Thanks to ttps://www.linuxjournal.com/article/4879
*/
#include <stdio.h>      /* puts, printf */
#include <time.h>       /* time_t, struct tm, time, localtime */
#include <cmath>
#include <X11/Xlib.h>

#define sinDegrees(x) sin((x) * M_PI / 180.0)
#define cosDegrees(x) cos((x) * M_PI / 180.0)

XGCValues gr_values;
XFontStruct *fontinfo;
GC gr_context;
XColor colour, dummy;
double hhang;
double mhang;

int main(){
  time_t time_ptr; 
  time_ptr = time(NULL); 
  
  // Get the localtime 
  tm* tm_local = localtime(&time_ptr); 

  Display *dsp = XOpenDisplay( NULL );
  if( !dsp ){ return 1; }

  fontinfo = XLoadQueryFont(dsp,"6x10");

  int screenNumber = DefaultScreen(dsp);
  unsigned long white = WhitePixel(dsp,screenNumber);
  unsigned long black = BlackPixel(dsp,screenNumber);
  Window win;

  if (tm_local->tm_hour >= 12) {
  win = XCreateSimpleWindow(dsp,
                               DefaultRootWindow(dsp),
                               50, 50,   // origin
                               200, 200, // size
                               0, white, // border
                               black );  // backgd
  } else {
  win = XCreateSimpleWindow(dsp,
                               DefaultRootWindow(dsp),
                               50, 50,   // origin
                               200, 200, // size
                               0, black, // border
                               white );  // backgd
  }

  XMapWindow( dsp, win );


  long eventMask = StructureNotifyMask;
  XSelectInput( dsp, win, eventMask );

  XEvent evt;
  do {
    XNextEvent( dsp, &evt );   // calls XFlush
  } while( evt.type != MapNotify );

  XAllocNamedColor(dsp, DefaultColormap(dsp, screenNumber),"red",
                      &colour,&dummy);
  gr_values.font = fontinfo->fid;
  gr_values.foreground = colour.pixel;

  GC gc = XCreateGC( dsp, win,
                     GCFont+GCForeground,        // mask of values
                     &gr_values );   // array of values
  if (tm_local->tm_hour >= 12) {
  XSetForeground( dsp, gc, white );
  hhang=-90.0 + (tm_local->tm_hour - 12) * 30.0 + tm_local->tm_min * 0.5 + tm_local->tm_sec * 0.00733;  
  mhang=-90.0 + tm_local->tm_min * 6 + tm_local->tm_sec * 0.1;
  XDrawLine(dsp, win, gc, 100, 100,100 + cosDegrees(hhang) * 40,100 + sinDegrees(hhang) * 40); //from-to
  XDrawLine(dsp, win, gc, 100, 100,100 + cosDegrees(mhang) * 80,100 + sinDegrees(mhang) * 80); //from-to
  XDrawLine(dsp, win, gc, 100, 100,99 + cosDegrees(hhang) * 40,99 + sinDegrees(hhang) * 40); //from-to
  XDrawLine(dsp, win, gc, 100, 100,99 + cosDegrees(mhang) * 80,99 + sinDegrees(mhang) * 80); //from-to
  XDrawLine(dsp, win, gc, 100, 100,101 + cosDegrees(hhang) * 40,101 + sinDegrees(hhang) * 40); //from-to
  XDrawLine(dsp, win, gc, 100, 100,101 + cosDegrees(mhang) * 80,101 + sinDegrees(mhang) * 80); //from-to
  } else {
  XSetForeground( dsp, gc, black );
  hhang=-90.0 + (tm_local->tm_hour - 12) * 30.0 + tm_local->tm_min * 0.5 + tm_local->tm_sec * 0.00733;
  mhang=-90.0 + tm_local->tm_min * 6 + tm_local->tm_sec * 0.1;
  XDrawLine(dsp, win, gc, 100, 100,100 + cosDegrees(hhang) * 40,100 + sinDegrees(hhang) * 40); //from-to
  XDrawLine(dsp, win, gc, 100, 100,100 + cosDegrees(mhang) * 80,100 + sinDegrees(mhang) * 80); //from-to
  XDrawLine(dsp, win, gc, 100, 100,99 + cosDegrees(hhang) * 40,99 + sinDegrees(hhang) * 40); //from-to
  XDrawLine(dsp, win, gc, 100, 100,99 + cosDegrees(mhang) * 80,99 + sinDegrees(mhang) * 80); //from-to
  XDrawLine(dsp, win, gc, 100, 100,101 + cosDegrees(hhang) * 40,101 + sinDegrees(hhang) * 40); //from-to
  XDrawLine(dsp, win, gc, 100, 100,101 + cosDegrees(mhang) * 80,101 + sinDegrees(mhang) * 80); //from-to
  }


  //XDrawLine(dsp, win, gc, 10, 10,190,190); //from-to
  //XDrawLine(dsp, win, gc, 10,190,190, 10); //from-to
  XDrawLine(dsp, win, gc, 100, 10,100,190); //from-to
  XDrawLine(dsp, win, gc, 10, 100,190,100); //from-to
  //XDrawLine(dsp, win, gc, 55, 10,145,190); //from-to
  //XDrawLine(dsp, win, gc, 145, 10,55,190); //from-to

  //XDrawLine(dsp, win, gc, 10, 55,190,145); //from-to
  //XDrawLine(dsp, win, gc, 10, 145,190,55); //from-to

  XDrawLine(dsp, win, gc, 43, 10,157,190); //from-to
  XDrawLine(dsp, win, gc, 157, 10,43,190); //from-to

  XDrawLine(dsp, win, gc, 10, 43,190,157); //from-to
  XDrawLine(dsp, win, gc, 10, 157,190,43); //from-to

  eventMask = ButtonPressMask|ButtonReleaseMask;
  XSelectInput(dsp,win,eventMask); // override prev
 
  do {
    XNextEvent( dsp, &evt );   // calls XFlush()
  } while( evt.type != ButtonRelease );


  XDestroyWindow( dsp, win );
  XCloseDisplay( dsp );

  return 0;
}

