#include "swatch.h"
#include <stream.h>

class swatch_helper {
   friend void clock_tick(XtPointer client_data, XtIntervalId *id);
   void update(StopWatch* sw, XtIntervalId ) {  long t; time(&t); sw->update(t); }
};

swatch_helper sh;

void clock_tick(XtPointer client_data, XtIntervalId *id)
{
   StopWatch* sw = (StopWatch*)client_data;
   sh.update(sw,*id);
}

void StopWatch::Go() 
{
//   PrintState("Go");
   if(iid==0 && state == Stopped) 
     { long ct; state = Running; time(&ct); start_time = ct; update(ct);}
}

void StopWatch::Stop() 
{ 
//    PrintState("Stop");
    if(state == Running) 
      { 
	 XtRemoveTimeOut(iid); state = Stopped; iid=0;
	 elapsed_time += current_time - start_time;
      }
}

void StopWatch::PrintState(char* str="")
{
   cerr << "State(" << str << "): ";
   if(state == StopWatch::Stopped)
     cerr << "Stopped\n";
   else if(state == StopWatch::Running)
     cerr << "Running\n";
   else
     cerr << "?=" << (int)state << "\n";
}

void StopWatch::Save()
{
   long ct;
   WatchState cs=state;
   Stop();
   time(&ct);
   file << ctime(&ct) << "   " << string << "\n";
   file.flush();
   cerr << "Stop Watch Saving...\n";
   elapsed_time = 0;
   update_string((long)0);
   time(&start_time);
   if(cs == Running)
     Go();
}

StopWatch::StopWatch(Widget parent , ofstream& f,  long interval)  
     :LabelWidget("stopwatch", parent), elapsed_time(0), iid(0), update_interval(interval), state(Running),
       file(f)
{
   (void) time(&start_time);
   strcpy(string,"00h 00m 00s");
//   PrintState("constructor");
   time(&start_time);
   update(start_time);
}
   
void StopWatch::update_string(long diff)
{
   struct tm tm;

   tm.tm_sec = (int)(diff%60);
   int mins = (int)(diff/60); // number of whole minutes
   tm.tm_min =  mins%60;
   tm.tm_hour  = mins/60; // number of whole hours

//   cerr << "diff= " << diff << " elapsed= " << elapsed_time << "\n";
#define SetTimeString(loc,val) \
   string[loc+1] = 48+val%10; \
   string[loc] = (val - (val%10))/10+48;

//   cerr << tm.tm_hour << "h" << tm.tm_min << "m" << tm.tm_sec << "s\n";
   SetTimeString(0,tm.tm_hour);
   SetTimeString(4,tm.tm_min);
   SetTimeString(8,tm.tm_sec);

#undef SetTimeString

   SetValues(XtNlabel,(XtArgVal)string);

}

void StopWatch::update(long ct)
{
// cannot use AppContext class because we dont have backpointer
// if  AppContext were a "direct" interface it would work
//  cerr << "update\n";

   iid = XtAppAddTimeOut(this->GetAppContext(), update_interval*1000, clock_tick, (XtPointer)this);
   current_time = ct;
   long diff = current_time - start_time;
   diff += elapsed_time; // number of whole seconds
	
   update_string(diff);
}
