//
// MainWindow.cpp 
//              
// Michael Tytgat, michael.tytgat@cern.ch 
//

#include <MainWindow.h>

using namespace std;

MainWindow::MainWindow( QWidget *parent, QApplication *app ) 
{
  myApp = app;
  myLayout = NULL;

  //Set up the console
  myconsole = new QTextEdit();
  myconsole->setReadOnly(1);
  myconsole->resize(300,200);
  //  myconsoledevice = new TextEditIoDevice(myconsole, this);
  //oconsole = new QTextStream();
  //oconsole->setDevice(myconsoledevice);
  //  oconsole.setDevice(new TextEditIoDevice(myconsole, this));
  connect(this, SIGNAL(consolewrite(const QString)), this,
          SLOT(printc(QString)));
 
  //Get library release
  char* SoftRel  = CAENHVLibSwRel();
  print("CAEN HV Wrapper Library Release: %s\n", SoftRel);
  
  //Set up the window layout
  initWindow();
}

void MainWindow::initWindow()
{  
  if (myLayout){
    delete myLayout;
    //qDeleteAll(this->children());
  }
  
  //initialise and set the buttons
  QHBoxLayout *mybuttons = new QHBoxLayout();
  QPushButton *quit = new QPushButton("Quit", this);
  if ( !init() ) { //If login failed, put the changeLogin button
    this->setWindowTitle("HVtest: login failed");
    QPushButton *changeLogin = new QPushButton("Change login parameters", this);
    connect( changeLogin, SIGNAL(clicked()), this, SLOT( changeLogin() ));
    mybuttons->addWidget(changeLogin);
    connect( quit, SIGNAL(clicked()), this, SLOT( quitloginfailed() ));
  } else {
    this->setWindowTitle("HVtest");

    myenviro = new enviro(this);
    QPushButton *enviroButton = new QPushButton("RPC Gas/Env. Data", this);
    connect( enviroButton, SIGNAL(clicked()), this, SLOT( Showenviro() ));
    mybuttons->addWidget( enviroButton );
    
    myA1526Control = new A1526Control(this); 
    QPushButton *A1526ControlButton = new QPushButton("A1526 Control", this);
    connect( A1526ControlButton, SIGNAL(clicked()), this, 
	     SLOT( ShowA1526Control() ));
    mybuttons->addWidget(A1526ControlButton);

    QPushButton* killButton = new QPushButton("Kill");
    connect(killButton, SIGNAL(clicked()), this, SLOT(kill()));
    mybuttons->addWidget(killButton);
    
    QPushButton* clearAlarmButton = new QPushButton("Clear Alarm");
    connect(clearAlarmButton, SIGNAL(clicked()), this, SLOT(clearAlarm()));
    mybuttons->addWidget(clearAlarmButton);
    
    connect( quit, SIGNAL(clicked()), this, SLOT( quit() ));
  }
  mybuttons->addWidget(quit);

  //Set Layout
  myLayout = new QGridLayout();
  myLayout->addWidget(myconsole, 1, 1);
  myLayout->addLayout(mybuttons, 2, 1);

  this->setLayout(myLayout);
  this->resize(700,400);
  this->show();
  
  this->setAttribute(Qt::WA_DeleteOnClose);

  myconsole->clear();
  printc("\t\t*** Welcome to HVtest ***\n\n");
}


/****************************************
 * To handle the messages of this class *
 ****************************************/
void MainWindow::printc(const QString theString )
{
  //*oconsole << theString;
  //oconsole->flush();
  myconsole->insertPlainText( theString );
}

void MainWindow::printc(const char* format, ...)
{
  QString premessage, message;
  premessage.sprintf("Main:\t");
  va_list args;
  va_start(args, format);
  //  *oconsole << message.sprintf("Main:\t");
  //*oconsole << message.vsprintf(format, args); 
  //oconsole->flush();
  //  oconsole << message.sprintf("\n");
  message.vsprintf(format, args);
  va_end(args);
  
  emit consolewrite(premessage+message);
}

void MainWindow::print(const char* format, ...)
{
  va_list args;
  va_start(args, format);
  printf("Main:\t");
  vprintf(format, args);
  va_end(args);
  //  printf("\n");
}

/*************************
 * Connect to the SY1527 *
 *************************/
bool MainWindow::init()
{
  print("Initialisation of the SY1527\n");
  int link = LINKTYPE_TCPIP;
  sprintf(buffer, "%s", "SY1527");
  char buffer1[20] = "157.193.99.196";
  char buffer2[50] = "admin";
  char buffer3[50] = "admin";
  name = buffer;
  char* arg = buffer1;
  char* userName = buffer2;
  char* passwd = buffer3;
  CAENHVRESULT result;

  //Get the IP, username and password from file
  ifstream readfile;
  readfile.open("login.dat");
  if(!readfile.is_open()){
    printc("No login.dat file found, using default settings:\n");
    ofstream writefile;
    writefile.open("login.dat", ios::trunc);
    writefile << arg << endl << userName << endl << passwd;
    writefile.close();
  } else {
    readfile >> buffer1 >> buffer2 >> buffer3;
    readfile.close();
  }
  print("IP: \t%s\n", arg);
  print("username: \t%s\n", userName);
  print("password: \t%s\n", passwd);
  
  result = CAENHVInitSystem(name, link, arg, userName, passwd);
  print("CAENHVInitSystem: %s (num. 0x%x)\n", CAENHVGetError(name), result);
  if( result == CAENHV_OK ){ 
    print("Connection with the SY1527 established\n");
    getCrateMap();
    return true;
  } else {    
    print("Connection with the SY1527 failed\n");
    return false;
  }
}

/****************************
 * change IP and login data *
 ****************************/
void MainWindow::changeLogin()
{
  char buffer1[50] = "157.193.99.196";
  char buffer2[50] = "admin";
  char buffer3[50] = "admin";
  char* arg = buffer1;
  char* userName = buffer2;
  char* passwd = buffer3;
  
  ifstream readfile;
  readfile.open("login.dat");
  if(!readfile.is_open()){
    print("No login.dat file found, using default settings:");
  } else {
    readfile >> buffer1 >> buffer2 >> buffer3;
    readfile.close();
  }
  myChangeLoginWindow = new ChangeLoginWindow(this, QString(arg), 
					      QString(userName), 
					      QString(passwd)); 
  myChangeLoginWindow->show();
}

ChangeLoginWindow::ChangeLoginWindow( MainWindow *parent, QString IP, 
				      QString userName, QString passwd )
{
  myMainWindow = parent;
    
  QLabel *IPLabel = new QLabel(tr("IP:"));
  QLabel *userNameLabel = new QLabel(tr("Username:"));
  QLabel *passwdLabel = new QLabel(tr("Password:"));
  IPEdit = new QLineEdit(IP);
  userNameEdit = new QLineEdit(userName);
  passwdEdit = new QLineEdit(passwd);

  QDialogButtonBox *buttonBox = 
    new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
  connect(buttonBox, SIGNAL(accepted()), this, SLOT(Accept()));
  connect(buttonBox, SIGNAL(rejected()), this, SLOT(Reject()));

  QGridLayout *myLayout = new QGridLayout();
  myLayout->addWidget(IPLabel, 0, 0);
  myLayout->addWidget(userNameLabel, 1, 0);
  myLayout->addWidget(passwdLabel, 2, 0);
  myLayout->addWidget(IPEdit, 0, 1);
  myLayout->addWidget(userNameEdit, 1, 1);
  myLayout->addWidget(passwdEdit, 2, 1);
  myLayout->addWidget(buttonBox, 3, 1);
  setLayout(myLayout);
}


void ChangeLoginWindow::Accept(){
    ofstream writefile;
    writefile.open("login.dat", ios::trunc);
    QByteArray ba1 = (IPEdit->text()).toLatin1();
    QByteArray ba2 = (userNameEdit->text()).toLatin1();
    QByteArray ba3 = (passwdEdit->text()).toLatin1();
    writefile << ba1.data() << endl << ba2.data() << endl << ba3.data();
    writefile.close();
    printf("Login data saved\n");
    printf("Restarting the initizialisation\n");
    this->close();
    myMainWindow->initWindow();
}

/*********************
 * Get the crate map *
 *********************/
void MainWindow::getCrateMap()
{
  unsigned short NrOfSl, *SerNumList, *NrOfCh;
  char *ModelList, *DescriptionList;
  unsigned char *FmwRelMinList, *FmwRelMaxList;
  CAENHVRESULT result;
  result = CAENHVGetCrateMap(name, &NrOfSl, &NrOfCh, &ModelList, 
			     &DescriptionList, &SerNumList,
			     &FmwRelMinList, &FmwRelMaxList );
  if ( result != CAENHV_OK ) 
    print("CAENHVGetCrateMap: %s (num. 0x%d)", CAENHVGetError(name), result);
  else {
    char *m = ModelList, *d = DescriptionList;
    print("System map:\n");
    for (int i = 0; i < NrOfSl; i++ , m += strlen(m) + 1, d += strlen(d) + 1 ) {
      if ( *m == '\0' ) 
	print("Board %2d: Not Present\n", i);
      else { 
	print("Board %2d: %s %s  (#ch: %d, Ser: %d, Rel: %d.%d)\n",
	      i, m, d, NrOfCh[i], SerNumList[i], FmwRelMaxList[i], 
	      FmwRelMinList[i]);
      }
    }
    free(SerNumList), free(ModelList), free(DescriptionList), 
      free(FmwRelMinList), free(FmwRelMaxList), free(NrOfCh);
  }
}

//----------------------------------------------------------------------
/**********************************
 * Show SetA1526Parameters window *
 **********************************/
void MainWindow::ShowA1526Control()
{
  myA1526Control->show();
  myA1526Control->raise();
  myA1526Control->activateWindow();
}

//----------------------------------------------------------------------

void MainWindow::Showenviro()
{
  myenviro->show();
  myenviro->raise();
}

//----------------------------------------------------------------------
/***********************************
 * quit, closeEvent and destructor *
 ***********************************/
void MainWindow::quit()
{
  printc("Closing HVtest ...\n");
  myA1526Control->globalstop();
  myApp->closeAllWindows();
  printc("Saving data and deinitialising HV\n");
  myA1526Control->save();
  // give some initial time to saving thread
  //sleep(5);
  //quit2();
  QTimer::singleShot(7000, this, SLOT(quit2())); 
}

void MainWindow::quit2()
{
  //printc("Waiting for running threads to finish ...\n");
  //QThreadPool *threadpool = QThreadPool::globalInstance();
  //threadpool->waitForDone();

  while( myA1526Control->notFinished() ) 
    sleep(1); // wait 1 second

  //delete myA1526Control;
  CAENHVRESULT result = CAENHVDeinitSystem(name);
  printc("Deinitialising of %s\n", name);
  if ( result == CAENHV_OK ) 
    printc("CAENHVDeinitSystem: Connection closed (num. 0x%x)\n", result);
  else 
    printc("CAENHVDeinitSystem: %s (num. 0x%x)\n", 
	   CAENHVGetError(name), result);

  myApp->quit();
}

void MainWindow::quitloginfailed() {
  myApp->quit();
}

void MainWindow::closeEvent(QCloseEvent *event){
  event->ignore();
}

MainWindow::~MainWindow(){}

/****************
 * Kill command *
 ****************/
void MainWindow::kill() {

  CAENHVRESULT result;
  result = CAENHVExecComm(name, "Kill");
  if (result == CAENHV_OK) printc("HV killed\n");
  printc("CAENHVExecComm: %s (num. 0x%x)\n", CAENHVGetError(name), result);

}


/***********************
 * Clear alarm command *
 ***********************/
void MainWindow::clearAlarm(){
    CAENHVRESULT result;
    result = CAENHVExecComm(name, "ClearAlarm");
    if (result == CAENHV_OK) printc("Alarm cleared\n");
    printc("CAENHVExecComm: %s (num. 0x%x)\n", CAENHVGetError(name), result);
}

