#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

#include <iostream>

#include "TROOT.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TLatex.h"
#include "TPaveLabel.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TLine.h"
#include "TArrow.h"
#include "TPolyLine.h"
#include "TBox.h"
#include "TPostScript.h"
#include "TEllipse.h"

#include "ShmObject.hh"
#include "DaqSlwControl.hh"

using namespace std;

bool continueJob=true;

void signalHandler(int signal) {
  std::cerr << "Process " << getpid() << " received signal "
            << signal << std::endl;
  continueJob=false;
}

int main(int argc, char *argv[]) {
  signal(SIGINT,signalHandler);
  signal(SIGTERM,signalHandler);

  ShmObject<DaqSlwControl> shmSlwControl(DaqSlwControl::shmKey);
  DaqSlwControl *p(shmSlwControl.payload());
  if(p==0) return 1;

  TApplication application("SlwMonitor Application",0,0);
  gROOT->Reset();
  gROOT->SetStyle("Plain");

  TCanvas canvas("SlwMonitor Canvas","SlwMonitor Canvas",200,100,250,300);
  canvas.Draw();

  TLine tLine[2];
  tLine[0]=TLine(0.3,0.2,0.3,0.1);
  tLine[1]=TLine(0.3,0.1,0.7,0.1);
  for(unsigned i(0);i<2;i++) {
    tLine[i].SetLineColor(1);
    tLine[i].SetLineWidth(5);
    tLine[i].Draw();
  }

  TArrow tArrow[6];
  tArrow[0]=TArrow(0.3,0.8,0.3,0.7);
  tArrow[1]=TArrow(0.3,0.6,0.3,0.5);
  tArrow[2]=TArrow(0.3,0.4,0.3,0.3);
  tArrow[3]=TArrow(0.7,0.1,0.7,0.2);
  tArrow[4]=TArrow(0.7,0.3,0.7,0.6);
  tArrow[5]=TArrow(0.7,0.7,0.7,0.8);
  for(unsigned i(0);i<6;i++) {
    tArrow[i].SetLineColor(1);
    tArrow[i].SetLineWidth(5);
    tArrow[i].Draw();
  }

  TPaveLabel *tPaveLabel[4];
  for(unsigned i(0);i<4;i++) {
    tPaveLabel[i]=new TPaveLabel(0.1,0.8-0.2*i,0.9,0.9-0.2*i,"JUNK");
    if(i==2) {
      delete tPaveLabel[i];
      tPaveLabel[i]=new TPaveLabel(0.1,0.8-0.2*i,0.5,0.9-0.2*i,"JUNK");
    }
  }

  tPaveLabel[0]->SetLabel(p->stateName(DaqSlwControl::dead).c_str());
  tPaveLabel[1]->SetLabel(p->stateName(DaqSlwControl::waiting).c_str());
  tPaveLabel[2]->SetLabel(p->stateName(DaqSlwControl::initialising).c_str());
  tPaveLabel[3]->SetLabel(p->stateName(DaqSlwControl::running).c_str());

  for(unsigned i(0);i<4;i++) {
    tPaveLabel[i]->Draw();
  }

  TPaveLabel tplStatus(0.1,0.92,0.4,0.98,"Status");
  tplStatus.SetFillColor(4);
  tplStatus.Draw();

  TPaveLabel tplCommand(0.6,0.92,0.9,0.98,"Command");
  tplCommand.SetFillColor(5);
  tplCommand.Draw();

  TPaveLabel transition[6]={
    TPaveLabel(0.3,0.72,0.5,0.78,RcdHeader::recordTypeName(RcdHeader::startUp).c_str()),
    TPaveLabel(0.3,0.52,0.5,0.58,RcdHeader::recordTypeName(RcdHeader::slowStart).c_str()),
    TPaveLabel(0.3,0.32,0.5,0.38,RcdHeader::recordTypeName(RcdHeader::slowControl).c_str()),
    TPaveLabel(0.4,0.02,0.6,0.08,RcdHeader::recordTypeName(RcdHeader::slowReadout).c_str()),
    TPaveLabel(0.7,0.52,0.9,0.58,RcdHeader::recordTypeName(RcdHeader::slowEnd).c_str()),
    TPaveLabel(0.7,0.72,0.9,0.78,RcdHeader::recordTypeName(RcdHeader::shutdown).c_str())
  };

  for(unsigned i(0);i<6;i++) {
    transition[i].Draw();
  }

  canvas.Update();







  unsigned nSleep(10);


  while(continueJob) {
    p->print(cout);

    for(int i(0);i<4;i++) {
      tPaveLabel[i]->SetFillColor(0);
      //tPaveLabel[i]->SetFillStyle(0);

      if(p->command()==i) {
	tPaveLabel[i]->SetFillColor(5);
	//tPaveLabel[i]->SetFillStyle(2001);
      }

      if(p->status()==i) {
	tPaveLabel[i]->SetFillColor(4);
	//tPaveLabel[i]->SetFillStyle(1001);
      }

      if(p->command()==i && p->status()==i) {
	tPaveLabel[i]->SetFillColor(3);
	//tPaveLabel[i]->SetFillStyle(1001);
      }

      tPaveLabel[i]->Draw();
    }


    RcdHeader transition(p->transition());
    RcdHeader::RecordType rt(transition.recordType());

    if(rt==RcdHeader::slowReadout) {
      tLine[0].SetLineColor(2);
      tLine[1].SetLineColor(2);
    } else {
      tLine[0].SetLineColor(1);
      tLine[1].SetLineColor(1);
    }
    tLine[0].Draw();
    tLine[1].Draw();

    for(unsigned i(0);i<6;i++) {
      tArrow[i].SetLineColor(1);
    }

    if(rt==RcdHeader::startUp)       tArrow[0].SetLineColor(2);
    if(rt==RcdHeader::slowStart)     tArrow[1].SetLineColor(2);
    if(rt==RcdHeader::slowControl)   tArrow[2].SetLineColor(2);
    if(rt==RcdHeader::slowReadout)   tArrow[3].SetLineColor(2);
    if(rt==RcdHeader::slowEnd)       tArrow[4].SetLineColor(2);
    if(rt==RcdHeader::shutdown)      tArrow[5].SetLineColor(2);

    for(unsigned i(0);i<6;i++) {
      tArrow[i].Draw();
    }

    canvas.Update();
    /*
    p->commandRegister();
    p->statusRegister();
    sleep(nSleep);
    p->unregister();
    */
  }
  
  for(unsigned i(0);i<4;i++) {
    delete tPaveLabel[i];
  }

  p->unregister();
  return 0;
}
