#ifndef SlwMonitor_HH
#define SlwMonitor_HH

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

#include <vector>
#include <fstream>
#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 "DaqSlwControl.hh"



class SlwMonitor {

private:
  class TArrowLoop {
    TArrowLoop(double xLo, double yLo, double xHi, double yHi) :
    _tVline(xLo,yHi,xLo,yLo),
    _tHline(xLo,yLo,xHi,yLo),
    _tArrow(xHi,yLo,xHi,yHi) {
    }

    void SetLineColor(int i) {
      _tVLine.SetLineColor(i);
      _tHLine.SetLineColor(i);
      _tArrow.SetLineColor(i);
    }

    void SetLineWidth(int i) {
      _tVLine.SetLineWidth(i);
      _tHLine.SetLineWidth(i);
      _tArrow.SetLineWidth(i);
    }

    void Draw() {
      _tVLine.Draw();
      _tHLine.Draw();
      _tArrow.Draw();
    }

  public:
    TLine  _tVLine;
    TLine  _tHLine;
    TArrow _tArrow;
  };


public:
  SlwMonitor() : _application("SlwMonitor Application",0,0),
		 _canvas("SlwMonitor Canvas","SlwMonitor Canvas",200,100,250,300),
		 _tArrowLoop(0.3,0.1,0.7,0.2),
		 _tplStatus(0.1,0.92,0.4,0.98,"Status"),
		 _tplCommand(0.6,0.92,0.9,0.98,"Command") {

    gROOT->Reset();
    gROOT->SetStyle("Plain");
    
    _canvas.Draw();

    _tArrowLoop.SetLineColor(1);
    _tArrowLoop.SetLineWidth(5);
    _tArrowLoop.Draw();
    
    _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();
    }

    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(dsc.stateName(DaqSlwControl::dead).c_str());
    _tPaveLabel[1]->SetLabel(dsc.stateName(DaqSlwControl::waiting).c_str());
    _tPaveLabel[2]->SetLabel(dsc.stateName(DaqSlwControl::initialising).c_str());
    _tPaveLabel[3]->SetLabel(dsc.stateName(DaqSlwControl::running).c_str());
    
    for(unsigned i(0);i<4;i++) {
      _tPaveLabel[i]->Draw();
    }

    _tplStatus.SetFillColor(4);
    _tplStatus.Draw();
    
    _tplCommand.SetFillColor(5);
    _tplCommand.Draw();
    
    _transition[0]=TPaveLabel(0.3,0.72,0.5,0.78,RcdHeader::recordTypeName(RcdHeader::startUp).c_str());
    _transition[1]=TPaveLabel(0.3,0.52,0.5,0.58,RcdHeader::recordTypeName(RcdHeader::slowStart).c_str());
    _transition[2]=TPaveLabel(0.3,0.32,0.5,0.38,RcdHeader::recordTypeName(RcdHeader::slowControl).c_str());
    _transition[3]=TPaveLabel(0.4,0.02,0.6,0.08,RcdHeader::recordTypeName(RcdHeader::slowReadout).c_str());
    _transition[4]=TPaveLabel(0.7,0.52,0.9,0.58,RcdHeader::recordTypeName(RcdHeader::slowEnd).c_str());
    _transition[5]=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();
  }

  virtual ~SlwMonitor() {
    for(unsigned i(0);i<4;i++) {
      delete tPaveLabel[i];
    }
  }

  bool state(const DaqSlwControl &dsc) {
    dsc.print(cout);
  
    for(int i(0);i<4;i++) {
      _tPaveLabel[i]->SetFillColor(0);
      //tPaveLabel[i]->SetFillStyle(0);
      
      if(dsc.command()==i) {
	_tPaveLabel[i]->SetFillColor(5);
	//tPaveLabel[i]->SetFillStyle(2001);
      }
      
      if(dsc.status()==i) {
	_tPaveLabel[i]->SetFillColor(4);
	//tPaveLabel[i]->SetFillStyle(1001);
      }
      
      if(dsc.command()==i && dsc.status()==i) {
	_tPaveLabel[i]->SetFillColor(3);
	//tPaveLabel[i]->SetFillStyle(1001);
      }
      
      _tPaveLabel[i]->Draw();
    }


    RcdHeader transition(dsc.transition());
    RcdHeader::RecordType rt(transition.recordType());
    
    if(rt==RcdHeader::slowReadout) {
      _tArrowLoop.SetLineColor(2);
    } else {
      _tArrowLoop.SetLineColor(1);
    }
    _tArrowLoop.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();
  }
  
private:
  TApplication _application;
  TCanvas _canvas;
  TArrow _tArrow[6];
  TArrowLoop _tArrowLoop;
  TPaveLabel _tplStatus;
  TPaveLabel _tplCommand;
  TPaveLabel *_tPaveLabel[4];
  TPaveLabel _transition[6];
};

#endif
