/***************************************************************************
                          newtwizard.cpp  -  description
                             -------------------
    begin                : Thu May 9 2002
    copyright            : (C) 2002 by Argo Vessmann (ARTEC Design)
    email                : 
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>

#include "../config.h"
#include "newtwizard.h"

#include <qstring.h>
#include <qstringlist.h>
#include <iostream.h>
#include <fstream.h>

#include <newt.h>

newtWizard::newtWizard()
{
	newtInit();
	newtCls();
	newtGetScreenSize( &maxcols, &maxrows );
	wcols = maxcols-16;
	wrows = maxrows-5;
}

newtWizard::~newtWizard()
{
	newtCls();
	newtFinished();
}

int newtWizard::exec( void )
{
	baseElements();

	currentpage = PG_WELCOME;
	int ret;
	while( 1 ) {
		ret = showPage();
		if ( currentpage == PG_WELCOME ) {
			if ( !Distro.testSystem() ) {
				currentpage = PG_ERROR;
				continue;
			}
		}
		if ( currentpage == PG_CARDCONF && ret == BUTTON_NEXT ) {
			(*currentcard).setFixedConf( TRUE );
			++currentcard;
			NetmosCardList *nlist = Distro.ExistingNetmosCards();
			if ( currentcard != nlist->end() )
				continue;
		}
		if ( currentpage == PG_CARDCONF && ret == BUTTON_PREV ) {
			NetmosCardList *nlist = Distro.ExistingNetmosCards();
			if ( currentcard != nlist->begin() ) {
				currentcard--;
				(*currentcard).setFixedConf( FALSE );
				continue;
			}
		}
		if ( currentpage == PG_CONFIRM && ret == BUTTON_PREV )
			currentcard--;
		if ( ret == BUTTON_CANCEL )
			return( ret );
		else if ( ret == BUTTON_NEXT )
			currentpage = nextpage;
		else if ( ret == BUTTON_PREV )
			currentpage = prevpage;
		else if ( ret == BUTTON_FINISH )
			return( 0 );
		if ( currentpage == PG_IDENTDISTRO && Distro.SupportedDistribution() )
			currentpage = PG_INFO;
	}
}

int newtWizard::showPage()
{

	nextpage = currentpage+1;
	prevpage = currentpage-1;
	switch( currentpage ) {
		case PG_WELCOME:
			PgWelcome();
			break;
		case PG_IDENTDISTRO:
			PgIdentDistro();
			break;
		case PG_INFO:
			PgInfo();
			break;
		case PG_CARDCONF:
			PgCardConf();
			break;
		case PG_CONFIRM:
			PgConfirm();
			break;
		case PG_FINISH:
			PgFinish();
			break;
		case PG_ERROR:
			PgError();
			break;
		default:
			cerr << "No such page" << currentpage << endl;
			exit( -1 );
			break;
	}

	newtComponent tmp = newtFormGetCurrent( form );
	int ret;
	if ( tmp == cancelbutton )
		ret = BUTTON_CANCEL;
	else if ( tmp == nextbutton )
		ret = BUTTON_NEXT;
	else if ( tmp == prevbutton )
		ret = BUTTON_PREV;
	else if ( tmp == finishbutton )
		ret = BUTTON_FINISH;

	cleanupWizPage();
	return ret;
}

int newtWizard::PgWelcome( void )
{

	prepareWizPage( "Welcome to Configurator" );

	QString l;
	l = "NetMos Configurator";
	newtComponent label = newtLabel( (wcols-l.length())/2, 1, (const char *)l );
//	newtComponent label = newtLabel( (wcols-l.length())/2, (wrows-5)/2, (const char *)l );
	newtComponent te = newtTextbox( 1, 3, wcols-4, wrows-9, NEWT_FLAG_WRAP|NEWT_FLAG_SCROLL );

	newtTextboxSetText( te, Distro.README() );

	newtFormAddComponents( form, label, te, NULL );
	addButtons( BUTTON_CANCEL|BUTTON_NEXT);

	newtRunForm( form );

	return 0;
}

void newtWizard::baseElements()
{
	QString verstr;

	verstr.sprintf( "Version %s", VERSION );
	newtDrawRootText( -(verstr.length()+1), 0, (const char *)verstr );
}

int newtWizard::PgIdentDistro( void )
{
	prepareWizPage( "Choose distribution" );

	int leftx = (wcols-8)/2;
	int topy = (wrows-3-4)/2;

	newtComponent label = newtLabel( 1, 1, "Current distribution not supported by this program." );
	QString l = "Choose distribution closest to your system";
	newtComponent labe2 = newtLabel( (wcols-l.length())/2, topy-1, (const char *)l );
	newtFormAddComponents( form, label, labe2, NULL );

	newtComponent rb[3];

	rb[0] = newtRadiobutton( leftx, topy, "SuSE 7.3", 1, NULL );
	rb[1] = newtRadiobutton( leftx, topy+1, "Mandrake", 0, rb[0] );
	rb[2] = newtRadiobutton( leftx, topy+2, "RedHat", 0, rb[1] );

	newtFormAddComponents( form, rb[0], rb[1], rb[2], NULL );
	addButtons();
	newtRunForm( form );

	if ( newtRadioGetCurrent(rb[0]) == rb[0] )
		Distro.setDistroType( DISTRO_TYPE_SUSE73 );
	else if ( newtRadioGetCurrent(rb[0]) == rb[1] )
		Distro.setDistroType( DISTRO_TYPE_MANDRAKE82 );
	else if ( newtRadioGetCurrent(rb[0]) == rb[2] )
		Distro.setDistroType( DISTRO_TYPE_REDHAT72 );

	return 0;
}

int newtWizard::PgInfo( void )
{
        char message[] = "I see that you have a graphical environment. But "
                       "i can't connect to it. The reason to this may be "
                        "that you have su-d to root and don't have enough "
                        "permissions to connect to graphical display.\n "
                        "If so then give in another window a command 'xhost +' "                        "and rerun this program."
                        "Then everyone everywhere can connect to you display. "
                        "After you have configured your Netmos card you can "
                        "give a command 'xhost -' to again disable access to "
                        "your display.";

	prepareWizPage( "System information" );
	newtComponent text1 = newtTextbox( 1, 1, wcols-4, (wrows-7)/2, NEWT_FLAG_WRAP|NEWT_FLAG_SCROLL );
	newtComponent label1 = newtLabel( 1, 0 , "Serial ports found" );
	newtComponent text2 = newtTextbox( 1, ((wrows-7)/2)+2, wcols-4, (wrows-7)/2, NEWT_FLAG_WRAP|NEWT_FLAG_SCROLL );
	newtComponent label2 = newtLabel( 1, ((wrows-7)/2)+1 , "Netmos cards found" );
	newtTextboxSetText( text2, message );
	newtComponentTakesFocus( text1, 1 );
	newtComponentTakesFocus( text2, 1 );

	SerialPortList *slist = Distro.ExistingSerialPorts();
#if ( QT_VERSION >= 300 )
	SerialPortList::iterator it;
#else
	SerialPortList::Iterator it;
#endif
	QString tmp;
	for( it=slist->begin(); it != slist->end(); ++it ) {
		if ( (*it).isDetected() && (*it).baud != -1 )
			tmp += (*it).InfoStrForNewt() + "\n";
	} 
	newtTextboxSetText( text1, (const char *)tmp );

	tmp = "";
	NetmosCardList *nlist = Distro.ExistingNetmosCards();
#if ( QT_VERSION >= 300 )
	NetmosCardList::iterator nit;
#else
	NetmosCardList::Iterator nit;
#endif
	for( nit=nlist->begin(); nit != nlist->end(); ++nit ) {
		tmp += (*nit).InfoStrForNewt() + "\n";
	}
	newtTextboxSetText( text2, (const char *)tmp );

	newtFormAddComponents( form, label1, text1, label2, text2, NULL );
	addButtons();

	newtRunForm( form );

	currentcard = nlist->begin();

	return 0;
}

int newtWizard::PgCardConf( void )
{
	QString ptitle;
	ptitle.sprintf( "Configuring card %s with id %s", (const char *)(*currentcard).CardName(), (const char *)(*currentcard).CardID() );
	prepareWizPage( ptitle );

	QStringList vserials = Distro.ValidSerials();

	newtComponent devlabel1 = newtLabel( 1, 2 , "Serial 1 on card" );
	newtComponent devlabel2 = newtLabel( 1, 6 , "Serial 2 on card" );
	newtComponent serdev1 = newtListbox( 18, 1, 3, NEWT_FLAG_SCROLL );
	newtComponent serdev2 = newtListbox( 18, 5, 3, NEWT_FLAG_SCROLL );
	for ( QStringList::Iterator it = vserials.begin(); it != vserials.end(); it++ ) {

		newtListboxAppendEntry( serdev1, (const char*)*it, (void *)&(*it) );
		newtListboxAppendEntry( serdev2, (const char*)*it, (void *)&(*it) );
	}

	newtComponent spdlabel1 = newtLabel( 34, 2 , "Speed" );
	newtComponent spdlabel2 = newtLabel( 34, 6 , "Speed" );
	int sparray[9] = { 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 };
	newtComponent serspd1 = newtListbox( 40, 1, 3, NEWT_FLAG_SCROLL );
	newtComponent serspd2 = newtListbox( 40, 5, 3, NEWT_FLAG_SCROLL );
	for( unsigned int i=0;i<sizeof( sparray )/sizeof(int);i++ ) {
		QString tmpnr;
		tmpnr = QString::number( sparray[i] );
		newtListboxAppendEntry( serspd1, (const char*)tmpnr, (void *)sparray[i] );
		newtListboxAppendEntry( serspd2, (const char*)tmpnr, (void *)sparray[i] );
	}
	newtListboxSetCurrentByKey( serspd1, (void *)115200 );
	newtListboxSetCurrentByKey( serspd2, (void *)115200 );

	if ( (*currentcard).hasSerials() ) {
		newtFormAddComponents( form, devlabel1, serdev1, spdlabel1, serspd1, NULL );
		if ( (*currentcard).isSerialConfigured( 0 ) )
			fillSerialValues( 0, serdev1, serspd1, &vserials, sizeof( sparray )/sizeof(int) );
	}
	if ( (*currentcard).has2SerialPorts() ) {
		newtFormAddComponents( form, devlabel2, serdev2, spdlabel2, serspd2, NULL );
		if ( (*currentcard).isSerialConfigured( 0 ) )
			fillSerialValues( 1, serdev2, serspd2, &vserials, sizeof( sparray )/sizeof(int) );
		QString *d1, *d2;
		d1 = (QString *)newtListboxGetCurrent( serdev1 );
		d2 = (QString *)newtListboxGetCurrent( serdev2 );
		if ( *d1 == *d2 ) {
			for ( QStringList::Iterator it = vserials.begin(); it != vserials.end(); it++ ) {
				if ( (*it) == *d2 ) {
					it++;
					if ( it == vserials.end() )
						it = vserials.begin();
					newtListboxSetCurrentByKey( serdev2, (void *)&(*it) );
					break;
				}
			}
		}
	}

	/** Parallel ports */
	newtComponent par1 = newtCheckbox( 2, 10, "Enable 1. parallel on card", '*', " *", NULL );
	newtComponent par2 = newtCheckbox( 2, 12, "Enable 2. parallel on card", '*', " *", NULL );
	newtComponent ecp1 = newtCheckbox( 33, 10, "ECP enabled", ' ', " *", NULL );
	newtComponent ecp2 = newtCheckbox( 33, 12, "ECP enabled", ' ', " *", NULL );

	newtComponent par[2], ecp[2];
	par[0] = par1; par[1] = par2;
	ecp[0] = ecp1; ecp[1] = ecp2;

	for( int i=0;i<2;i++ ) {
		if ( (*currentcard).hasParallel( i ) ) {
			newtFormAddComponents( form, par[i], ecp[i], NULL );
			if ( (*currentcard).parallelenabled( i ) ) {
				newtCheckboxSetValue( par[i], '*' );
				if ( (*currentcard).parallelECP( i ) )
					newtCheckboxSetValue( ecp[i], '*' );
			}
		}
	}

	addButtons();

	while( 1 ) {
		newtRunForm( form );
		QString *s1, *s2;
		s1 = s2 = NULL;
		if ( (*currentcard).hasSerials() ) 
			s1 = (QString *)newtListboxGetCurrent( serdev1 );
		if ( (*currentcard).has2SerialPorts() )
			s2 = (QString *)newtListboxGetCurrent( serdev2 );
		if ( Distro.suitableSerials( s1, s2 ) )
			break;
		newtComponent tmp = newtFormGetCurrent( form );
		if ( tmp != nextbutton )
			break;
		newtCenteredWindow( maxcols/2, 8, "Error" );
		newtComponent badserials = newtLabel( ((maxcols/2)-25)/2, 2 , "These serials do not fit." );
		newtComponent errorok = newtButton( ((maxcols/2)-6)/2, 4, "Ok" );
		newtComponent errorform = newtForm( NULL, NULL, 0 );
		newtFormAddComponents( errorform, badserials, errorok, NULL );
		newtRunForm( errorform );
		newtFormDestroy( errorform );
		newtPopWindow();

	}
	if ( (*currentcard).hasSerials() ) {
		readOneSerialConf( 0, serdev1, serspd1 );
	}
	if ( (*currentcard).has2SerialPorts() ) {
		readOneSerialConf( 1, serdev2, serspd2 );
	}
	for( int i=0;i<2;i++ ) {
		if ( (*currentcard).hasParallel( i ) )
			readOneParallelConf( i, par[i], ecp[i] );
	}
	return 0;
}

int newtWizard::PgConfirm( void )
{
	prepareWizPage( "Confirm configuration" );

#if ( QT_VERSION >= 300 )
	NetmosCardList::iterator nit;
#else
	NetmosCardList::Iterator nit;
#endif
	QString info;
	NetmosCardList *nlist = Distro.ExistingNetmosCards();
	for( nit=nlist->begin(); nit != nlist->end(); ++nit ) {
		(*nit).sprintConfiguration( &info );
	}

	newtComponent te = newtTextbox( 1, 1, wcols-4, wrows-7, NEWT_FLAG_WRAP|NEWT_FLAG_SCROLL );

	info = convertRichText( info );
	newtTextboxSetText( te, (const char *)info );

	newtFormAddComponent( form, te );

	addButtons();

	newtRunForm( form );

	return 0;
}

int newtWizard::PgFinish( void )
{
	bool status = Distro.saveConf();

	if ( status )
		prepareWizPage( "Complete" );
	else
		prepareWizPage( "Error" );


	newtComponent te = newtTextbox( 1, 1, wcols-4, wrows-7, NEWT_FLAG_WRAP|NEWT_FLAG_SCROLL );

	QString info;
	if ( status )
		info = Distro.saveOkMsg();
	else
		info = Distro.ErrorMsg();
	newtTextboxSetText( te, (const char *)info );

	newtFormAddComponent( form, te );

	addButtons(BUTTON_CANCEL|BUTTON_FINISH);

	newtRunForm( form );

	return 0;
}

int newtWizard::PgError( void )
{
	prepareWizPage( "Error" );

	QString info = Distro.ErrorMsg();

	newtComponent te = newtTextbox( 1, 1, wcols-4, wrows-7, NEWT_FLAG_WRAP|NEWT_FLAG_SCROLL );

	info = convertRichText( info );
	newtTextboxSetText( te, (const char *)info );

	newtFormAddComponent( form, te );

	addButtons(BUTTON_CANCEL|BUTTON_FINISH);

	newtRunForm( form );

	return 0;
}

void newtWizard::readOneParallelConf( int nr, newtComponent par, newtComponent ecp )
{
	if ( newtCheckboxGetValue( par ) == '*' ) {
		(*currentcard).setParallel( nr, TRUE );
		if ( newtCheckboxGetValue( ecp ) == '*' )
			(*currentcard).setParallelECP( nr, TRUE );
		else
			(*currentcard).setParallelECP( nr, FALSE );
	} else {
		(*currentcard).setParallel( nr, FALSE );
		(*currentcard).setParallelECP( nr, FALSE );
	}
}

void newtWizard::readOneSerialConf( int nr, newtComponent dev, newtComponent sp )
{
	SerialPortList *slist = Distro.ExistingSerialPorts();
#if ( QT_VERSION >= 300 )
	SerialPortList::iterator it;
#else
	SerialPortList::Iterator it;
#endif
	QString *gstr = (QString *)newtListboxGetCurrent( dev );
	for( it=slist->begin(); it != slist->end(); ++it ) {
		if ( (*it).DevName() == *gstr )
			break;
	}
	if ( it == slist->end() ) {
		SerialPort po;
		po.clean();
		QString tmp = gstr->mid( 9, 2 );
		po.port = tmp.toInt();
		it = slist->append( po );
	}
	int nspeed = (int)newtListboxGetCurrent( sp );
	(*it).setSpeed( nspeed );
	(*currentcard).setSerial( nr, &(*it) );
}


void newtWizard::fillSerialValues( int nr, newtComponent dev, newtComponent sp, QStringList *keys, int spcount )
{
	QString cdevname = (*currentcard).serialDevName( nr );
	for ( QStringList::Iterator it = keys->begin(); it != keys->end(); it++ ) {
		if ( cdevname == (*it) ) {
			newtListboxSetCurrentByKey( dev, (void *)&(*it) );
		}
	}
	int cspeed = (*currentcard).serialDevSpeed( nr );
	void *pvalue = newtListboxGetCurrent( sp );
	int i;
	for( i=0; i<spcount;i++ ) {
		newtListboxSetCurrent( sp, i );
		int tnr = (int)newtListboxGetCurrent( sp );
		if ( tnr == cspeed )
			break;
	}
	if ( i == spcount )
		newtListboxSetCurrentByKey( sp, pvalue );
}

void newtWizard::prepareWizPage( const char *title )
{
	newtCenteredWindow( wcols, wrows, title );

	form = newtForm( NULL, NULL, NEWT_FLAG_NOF12 );
}

void newtWizard::addButtons( int which = BUTTON_DEFAULT )
{
	if ( which & BUTTON_CANCEL ) {
		cancelbutton = newtButton( 2, wrows-5, "Cancel" );
		newtFormAddComponent( form, cancelbutton );
	} else
		cancelbutton = NULL;
	if ( which & BUTTON_PREV ) {
		prevbutton = newtButton( wcols-24, wrows-5, "Prev" );
		newtFormAddComponent( form, prevbutton );
	} else
		prevbutton = NULL;
	if ( which & BUTTON_FINISH ) {
		finishbutton = newtButton( wcols-13, wrows-5, "Finish" );
		newtFormAddComponent( form, finishbutton );
		newtFormSetCurrent( form, finishbutton );
	} else
		finishbutton = NULL;
	if ( which & BUTTON_NEXT ) {
		nextbutton = newtButton( wcols-13, wrows-5, "Next" );
		newtFormAddComponent( form, nextbutton );
		newtFormSetCurrent( form, nextbutton );
	} else
		nextbutton = NULL;

}

void newtWizard::cleanupWizPage( void )
{
	newtFormDestroy( form );
	newtPopWindow();
}
QString newtWizard::convertRichText( QString str )
{
	QString resp;
	bool skipchars = FALSE;
	for( unsigned int i=0;i<str.length();i++ ) {
		if ( str[i] == '<' )
			skipchars = TRUE;
		if ( str[i] == '>' ) {
			skipchars = FALSE;
			continue;
		}
		if ( !skipchars )
			resp += str[i];
	}
	return( resp );
}
