#include "shellExec.h"
#include "shellExec.moc"
#include <stdio.h>
#include <kapp.h> 				/* klocale is defined there */
#include <kiconloader.h>
#include <ktablistbox.h>
#include <qaccel.h>
#include <stdlib.h>
#include <qcolor.h>
extern KApplication* TemplateApplication; 	/* defined in main.cpp */

#define LPC_STATUS 	1
#define LPC_PRINTCAP 	2
#define LPC_HOLDALL 	3
#define LPC_NOHOLDALL   4
#define LPC_RELEASE     5
#define LPC_HOLD	6


//#include "../../config.h"
//#define LPC_BIN "/usr/local/bin/lpc"
//#define LPQ_BIN "/usr/local/bin/lpq"
//#define LPRM_BIN "/usr/local/bin/lprm"

// TODO LPC_* are absolute PATH replace with QStrings !!



shellExec::shellExec() 
//(QWidget *parent=0, const char *name=0) : QWidget(parent, name)
{
    selectedPrinter="all";
    lpqbuf=0L;
#define LPQBUF_SIZE 32*1024
    lpqbuf = (char *)malloc(LPQBUF_SIZE); // Hope this long enough
    lpqbufrun = lpqbuf;
    lpqstdout=0;

    /* Start a lpq Proces in Order to get something into the Queue ListBox */
    
    lpq = new KProcess;
    *lpq << "lpq";
    connect( lpq, SIGNAL(receivedStdout(KProcess *, char *, int)), 
   	     this,  SLOT(LpqReadStdout( KProcess *, char *, int)) );
    connect( lpq, SIGNAL(processExited(KProcess *)), 
             this,  SLOT(LpqProcessExited(KProcess *)) );
	
    *lpq << "-Pall";
    if( lpq->start( KProcess::Block, KProcess::Stdout ) )
      {
      }	

    /* lpc is used for finding out which Printer instaled on the local System
     */
    lpc = new KProcess;
    *lpc << "lpc";
    connect( lpc, SIGNAL(receivedStdout(KProcess *, char *, int)),
   	     this, SLOT(LpcReadStdout(KProcess *, char *, int)) );
    connect( lpc, SIGNAL(processExited(KProcess *)), 
	     this, SLOT(LpcProcessExited(KProcess *)) );
	
    *lpc << "printcap";
    *lpc << "all";

    LpcCommand = LPC_PRINTCAP;
    if( lpc->start( KProcess::Block, KProcess::Stdout ) )
      {
      }	

    lprm = new KProcess;
    *lprm << "lprm";
    holdall=0;  	// holdall = false
    HoldAllStatus();

}

/**
 *  lpc_execute
 */

void
shellExec::LpcExecute()
{
  LpcBuffer = "";
 
    lpc->clearArguments();
    *lpc << "lpc";
    QApplication::setOverrideCursor( waitCursor );
    switch(LpcCommand)
      {
      case LPC_STATUS:
	*lpc << "-P";
	*lpc <<  selectedPrinter.data();
    	*lpc << "status";
	break;
      
      case LPC_PRINTCAP:    
	*lpc << "printcap";
	*lpc << "all";
	break;
      
      case LPC_RELEASE:
	*lpc << "release";
	*lpc << selectedPrinter.data();
	*lpc << "all";
	break;

      case LPC_HOLD:
	*lpc << "hold";
	*lpc << selectedPrinter.data();
	*lpc << "all";	
	break;

      case LPC_HOLDALL:
	*lpc << "-P";
	*lpc << selectedPrinter.data();
	*lpc << "holdall";
	break;
      
      case LPC_NOHOLDALL:
     	*lpc << "-P";
	*lpc << selectedPrinter.data();
	*lpc << "noholdall";
	break;
      }
    lpc->start( KProcess::Block, KProcess::Stdout );
    QApplication::restoreOverrideCursor();
}
void
shellExec::HoldAll()
{
  LpcCommand = LPC_HOLDALL;
  LpcExecute();
  LpcCommand = LPC_HOLD;
  LpcExecute();
  ListPrintQueue();
}
void 
shellExec::ReleaseAll()
{
  LpcCommand = LPC_NOHOLDALL;
  LpcExecute();
  HoldAllStatus();
  LpcCommand = LPC_RELEASE;
  LpcExecute();
  ListPrintQueue();
}
void
shellExec::HoldAllStatus()
{
  // feststellen mit lpc ob printer im holdall stehen
  //
  LpcCommand = LPC_STATUS;
  LpcExecute();
 // QString pixdir; // = TemplateApplication->kdedir() +
 // QString("/share/apps/klpc/toolbar/");  
    if (holdall == 0)
    {
	//QPixmap play_pixmap((pixdir + "play.xpm").data());
	//toolbar->setButtonPixmap(PMBUTTON2, play_pixmap);
    	//FIXME
	//statusbar->changeItem("Druckerstatus: bereit", ID_LINE_COLUMN);
	}
      else
	{
	//QPixmap pause_pixmap((pixdir + "pause.xpm").data());
	//toolbar->setButtonPixmap(PMBUTTON2, pause_pixmap);
    	//FIXME
	//statusbar->changeItem("Druckerstatus: angehalten", ID_LINE_COLUMN);
	}	
	
}


void
shellExec::RemoveJob()
{

//   char buffer[256];
// 
//   /* No selection no remove job */
//   if (ListBox->currentItem () == -1)
//     return;
//   /* Change to a wait-cursor (in case it takes some time)*/
//   QApplication::setOverrideCursor (waitCursor);
// 
//   /* Now we must now what printer and which job number */
//   QString printername = ListBox->text (ListBox->currentItem (), 0);
//   QString jobnumber   = ListBox->text (ListBox->currentItem (), 4);
//   
//   lprm->clearArguments ();
//   /* FIXME: we should use a configured path for lprm here */
//   *lprm << "lprm" << "-P" << printername.data () << jobnumber.data ();
//   
//   /* Start the lprm Remove */
//   lprm->start (KProcess:: Block, KProcess::Stdout);
//   
//   ListPrintQueue ();
// 
//   /* Restore our Cursor that we changed to wait before */
//   QApplication::restoreOverrideCursor ();
// 
}


void
shellExec::ListPrintQueue ()
{
  /* Test if there is another lpq (which was started from us) is running */
  if (lpqrunning == 1)
    return;

  lpqrunning = 1;
  LpqBuffer = "";
  lpqbufrun = lpqbuf;
  memset (lpqbuf, 0, LPQBUF_SIZE);
  lpq->clearArguments ();

  /* FIXME: we should use a configured path for lpq here */
  *lpq << "lpq" << "-P" << selectedPrinter.data ();

  if (lpq->start (KProcess::Block, KProcess::Stdout)) {
    //   printf ("Fehler!\n");
  }
  lpqrunning = 0;
  // HoldAllStatus();
}

/*
 * Read Stdout of lpq
 */

void 
shellExec::LpqReadStdout(KProcess *, char *buffer, int len)
{
/* There is a timing problem here. When this routine is executed
   too long ->SEGFAULT
*/
	/* Copy lightining fast */
	strncpy(lpqbufrun, buffer, len);
	lpqbufrun+=len;
}

/*
 * We get notified if lpq-Process exits
 */

void
shellExec::LpqProcessExited(KProcess *)
{
  const char *start = (const char *) lpqbuf;
  LpqBuffer = QString (lpqbuf, lpqbufrun - lpqbuf);
  const char *end = start;
  int len = 0;
  char buffer[256];
  int search = 1;

  QList <QString >* list = new QList <QString>();
  QString actualPrinter;

  while (*end != 0) {
    while (*end++ != '\n')
      len++;
    strncpy ((char *) &buffer, start, len);
    //printf("***%s\n",(char *)&buffer);
    buffer[len] = 0;
    start = end;
    len = 0;

    char dummy[128];
    char printername[32];

    sscanf ((char *) &buffer, "%s%s", (char *) &dummy, (char *) &printername);
    
    if (QString (dummy) == "Printer:") {
      actualPrinter = QString (printername);
    }

    //FIXME we should handle bounce queues special
    // because "lpq" shows them special
    if (strstr ((char *) &buffer, "bounce") != 0L && search) {
 //     printf ("***found bounce queue\n");
      search = 0;		// Stop search 

    }

    // Keine Spaces, keine [P]rinter und keine Leerzeilen
    // FIXME this place memory leaks!!!
    if (buffer[0] != ' ' && buffer[0] != 'P' && buffer[0] != 0) {
      QString *tmp;
      tmp = new QString(); // FIXME Memory Leak (nowhere deleted)
      tmp->append(actualPrinter.data());
      tmp->append(" ");
      tmp->append(buffer);
	list->append(tmp);
    }
  }
	
	// emit parent UpdateListBox
	return ;
}


void 
shellExec::LpcReadStdout(KProcess *, char *buffer, int len)
{
/* Es scheint timing-Probleme zu geben, falls diese Routine zu lange
   ist
*/
	for ( int i= 0; i < len; i++ )
		LpcBuffer += *(buffer+i);

}

/*
 + We get notified if lpq-Process exits
 */

void 
shellExec::LpcProcessExited(KProcess *)
{

	const char *start = (const char *) LpcBuffer;
	const char *end = start;
	int len = 0;
	char buffer[256];

	while (*end != 0)
	{
		while (*end++ != '\n')
			len++;
		strncpy ((char *) &buffer, start, len);
		buffer[len] = 0;
		start = end;
		len = 0;
		switch (LpcCommand)
		{
		case LPC_PRINTCAP:
			{	// Extract Printers 

				if (buffer[0] != ' ')
				{
					QString *dummy = new QString (buffer);

					PrinterList.append (dummy);
				}
			}
			break;

		case LPC_STATUS:
			{
				if (buffer[0] != ' ')
					if (strstr ((char *) &buffer, "(holdall)") == NULL)
						holdall = 0;
					else
						holdall = 1;
			}
			break;
		case LPC_RELEASE:
		case LPC_HOLDALL:
			break;
		}
	}

}
shellExec::~shellExec()
{
  free(lpqbuf);
  delete lprm;
  delete lpq;
  delete lpc;
}
