/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            cprquerydialog.cc
 *
 *  Sat Feb 19 17:05:43 CET 2005
 *  Copyright  2005 Bent Bisballe
 *  deva@aasimon.org
 ****************************************************************************/

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include <config.h>
#ifdef USE_GUI

#include <qframe.h>

#include "messagebox.h"
#include "cprquerydialog.h"
#include "miav_config.h"

CPRQueryDialog::CPRQueryDialog(QLabel *lcpr,
                               QLabel *lname,
                               QWidget *parent, 
                               const char *name)
	: QDialog(parent, name, TRUE)
{
  MiavConfig cfg("cprquery.conf");

  lbl_name = lname;
  lbl_cpr = lcpr;

  //Read configuration
  CPR_HOST = cfg.readString("cpr_host");
  CPR_PORT = cfg.readInt("cpr_port");

  cpr[0] = '\0';
  internalCpr[0] = '\0';	

  cprSocket = new QSocket(this);
  connect(cprSocket, SIGNAL(readyRead()), SLOT(cprSocket_readyRead()));
  connect(cprSocket, SIGNAL(connected()), SLOT(cprSocket_connected()));

  lbl_cpr->setText("Indtast CPR");

  // Generate input buttons
	QGridLayout *gl = new QGridLayout(this, 4, 3, 10, 2);

	QButton *b1 =  createButton(this, "1", 1);
	QButton *b2 =  createButton(this, "2", 2);
	QButton *b3 =  createButton(this, "3", 3);
	QButton *b4 =  createButton(this, "4", 4);
	QButton *b5 =  createButton(this, "5", 5);
	QButton *b6 =  createButton(this, "6", 6);
	QButton *b7 =  createButton(this, "7", 7);
	QButton *b8 =  createButton(this, "8", 8);
	QButton *b9 =  createButton(this, "9", 9);
	QButton *b0 =  createButton(this, "0", 0);
	QButton *bbs = createButton(this, "<-", 10);
	QButton *bca = createButton(this, "CA", 11);

	gl->addWidget(b1, 0,0);
	gl->addWidget(b2, 0,1);
	gl->addWidget(b3, 0,2);
	gl->addWidget(b4, 1,0);
	gl->addWidget(b5, 1,1);
	gl->addWidget(b6, 1,2);
	gl->addWidget(b7, 2,0);
	gl->addWidget(b8, 2,1);
	gl->addWidget(b9, 2,2);
	gl->addWidget(b0, 3,1);
	gl->addWidget(bbs, 3,2);
	gl->addWidget(bca, 3,0);

	// Setup signals
	connect(b1, SIGNAL(clicked()), SLOT(b_1_clicked()));
	connect(b2, SIGNAL(clicked()), SLOT(b_2_clicked()));
	connect(b3, SIGNAL(clicked()), SLOT(b_3_clicked()));
	connect(b4, SIGNAL(clicked()), SLOT(b_4_clicked()));
	connect(b5, SIGNAL(clicked()), SLOT(b_5_clicked()));
	connect(b6, SIGNAL(clicked()), SLOT(b_6_clicked()));
	connect(b7, SIGNAL(clicked()), SLOT(b_7_clicked()));
	connect(b8, SIGNAL(clicked()), SLOT(b_8_clicked()));
	connect(b9, SIGNAL(clicked()), SLOT(b_9_clicked()));
	connect(b0, SIGNAL(clicked()), SLOT(b_0_clicked()));
	connect(bbs,SIGNAL(clicked()), SLOT(b_b_clicked()));
	connect(bca,SIGNAL(clicked()), SLOT(b_c_clicked()));
	
	this->move(175,150);
  show();
}

CPRQueryDialog::~CPRQueryDialog()
{
}

QPushButton *CPRQueryDialog::createButton(QWidget *parent, const char *text, int value) 
/* A genric button-creater */
{
  char buf[32];
  sprintf(buf, "%d", value);
  QPushButton *q = new QPushButton(this, buf);
  
	QFont f("Lucida", 48);
	q->setFixedSize(150, 100);
	q->setText(text);
	q->setFont(f);
	return q;
}

/* Event function for handling buttonclicks.
 * For button 0-9 the values is sent back.
 * Backspace and clear are handled via special
 * signals.
 * When 10 digits has been input we close the form
 */
void CPRQueryDialog::b_1_clicked() { insert_digit(1); }
void CPRQueryDialog::b_2_clicked() { insert_digit(2); }
void CPRQueryDialog::b_3_clicked() { insert_digit(3); }
void CPRQueryDialog::b_4_clicked() { insert_digit(4); }
void CPRQueryDialog::b_5_clicked() { insert_digit(5); }
void CPRQueryDialog::b_6_clicked() { insert_digit(6); }
void CPRQueryDialog::b_7_clicked() { insert_digit(7); }
void CPRQueryDialog::b_8_clicked() { insert_digit(8); }
void CPRQueryDialog::b_9_clicked() { insert_digit(9); }
void CPRQueryDialog::b_0_clicked() { insert_digit(0);}
void CPRQueryDialog::b_b_clicked() { remove_digit();}
void CPRQueryDialog::b_c_clicked() { remove_all();}

void CPRQueryDialog::b_clicked(int value) 
{
  printf("%d\n", value);
	switch(value) {
		case 10:
			if (digits>0) digits--;
			emit bbs_clicked();
			break;
		case 11:
			digits = 0;
			emit bca_clicked();
			break;
		default:
			digits++;
			emit number_clicked(value);
	}		
	if (digits == 10){
		digits = 0;
		accept();
	}
}

void CPRQueryDialog::run(int pos) 
/* This is where the mgui thread starts.
 * Open a inputwindow and prepare to receive a cpr
 */ 
{

  //  iw = new CPRQueryDialog(this, "Input", true, pos);
  

  // TODO : Reconnect
  /*
  if (this->exec() == QDialog::Accepted) {
#ifdef WITH_DV
    camera->setCpr(cpr);
#endif
    verifycpr(cpr);
  }
  */
}

void CPRQueryDialog::remove_digit() 
/* Remove one digit from the selected cpr
 * Used when the user pushes backspace in
 * the inputwindow
 */
{
  int temp;
  temp = strlen(cpr);
  if (temp == 7) /* Remove two characters due to the hyphen */
    strcpy(cpr+temp-2, "\0");
  else if ((temp >0) && (temp <=11))
    strcpy(cpr+temp-1, "\0");
  lbl_cpr->setText(cpr);
}

void CPRQueryDialog::remove_all() 
/* Clear the selected cpr */
{
  strcpy(cpr, "");
  lbl_cpr->setText(cpr);
}

void CPRQueryDialog::insert_digit(int value)
/* Respond to what the user types in the inputWindow */
{
  char temp[2];
  switch(strlen(cpr)) {
  case 5: // Automaticaly add a hyphen after the sixth digit
    sprintf(temp, "%d-", value);
    strcat(cpr, temp);
    lbl_cpr->setText(cpr);
    break;
  case 10:
    sprintf(temp, "%d", value);
    strcat(cpr, temp);
    lbl_cpr->setText(cpr);
    verifycpr(cpr);
    break;
  default:
    sprintf(temp, "%d", value);
    strcat(cpr, temp);
    lbl_cpr->setText(cpr);
    break;
  }
}

void CPRQueryDialog::verifycpr(char *cpr) 
/* Test a cpr via test_cpr().
 * If cpr is invalid, then ask user what
 * to do via confirmCprWindow
 */
{
  strncpy(internalCpr, cpr, 6);
  strncpy(internalCpr+6, cpr+7, 4);
  internalCpr[10] = 0;
  
  if (!(test_cpr(internalCpr))) {
    MessageBox ccw(this, "Bekr�ft", "Ugyldigt CPR nummer, brug det alligevel?", TYPE_YES_NO_CANCEL);
    switch(ccw.exec()) {
    case MSG_CANCEL:
      bedit_clicked();
      break;
    case MSG_NO:
      bcancel_clicked();
      break;
    case MSG_YES:
      accept();
      break;
    }
  } else {
    cprSocket->connectToHost(CPR_HOST->c_str(), CPR_PORT);
    accept();
  }
}


void CPRQueryDialog::bcancel_clicked()
/* Clears all data - alerts user if measurements are not stored */
{
  cpr[0]= '\0';
  lbl_cpr->setText("Indtast CPR");
  lbl_name->setText("");
  run(0);
}

void CPRQueryDialog::bedit_clicked() 
/* This is used when the user enters a cpr that is not valid and wishes to edit
 * the cpr.
 */
{
  cpr[10]= '\0';
  lbl_cpr->setText(cpr);
  lbl_name->setText("");
  run(9);
}


int CPRQueryDialog::test_cpr(const char *s)
/* Checks that a cpr i valid via a modulo11 test */
{
  int sum = 0;
  int ctl;
  const char *cptr;
  
  if(strlen(s) != 10)
    return 0;
  
  for(cptr = s; *cptr; cptr++)
    {
      if(!isdigit(*cptr))
	return 0;
    }
  sum += (s[0] - '0') * 4;
  sum += (s[1] - '0') * 3;
  sum += (s[2] - '0') * 2;
  sum += (s[3] - '0') * 7;
  sum += (s[4] - '0') * 6;
  sum += (s[5] - '0') * 5;
  sum += (s[6] - '0') * 4;
  sum += (s[7] - '0') * 3;
  sum += (s[8] - '0') * 2;
  ctl = 11 - (sum % 11);
  if(ctl == 11)
    ctl = 0;
  return s[9] - '0' == ctl;
}

void CPRQueryDialog::cprSocket_readyRead() 
/* Uses a patients cpr to look up his or hers name
 * via the departments cpr-server.
 * This is called by the cprSocket when the socket is ready
 */
{
  QString name;
  QString firstname;
  QString lastname;
  int timeout = 0;
  if (!cprSocket->canReadLine())
    return;
  while(cprSocket->canReadLine()) {
    QString s = cprSocket->readLine();
    if (s.startsWith("0001")) {
      name.append(s.right(s.length()-4));
      lastname.append(s.right(s.length()-4));
      name.setLength(name.length()-1);
      if (name.length())
	name += QString(", ");
      
    }
    if (s.startsWith("0002")) {
      name.append(s.right(s.length()-4));
      firstname.append(s.right(s.length()-4));
      name.setLength(name.length()-1);
      cprSocket->close();
      lbl_name->setText(name);
      return;
    }
    if (timeout>1000)
      {
	lbl_name->setText(NAME_NOT_AVAILABLE);
	return;
      }
    timeout++;
  }
}


void CPRQueryDialog::cprSocket_connected() 
/* Writes the selected cpr to the cpr-server
 * when the cprSocket is connected.
 */
{	
  cprSocket->writeBlock(internalCpr, 10);
  cprSocket->writeBlock("\n", 1);
}

#endif /* USE_GUI */