/***************************************************************************
                          kweather.cpp  -  description
                             -------------------
    begin                : Wed Jul  5 23:09:02 CDT 2000
    copyright            : (C) 2000 by Ian Reinhart Geiser
    email                : geiseri@msoe.edu
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 <qfile.h>
#include <qcursor.h>
#include <kaboutdata.h>
#include <kaboutapplication.h>
#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <kpopupmenu.h>
#include <kconfig.h>
#include <kstandarddirs.h>

#include "kweather.h"

extern "C"
{
    KPanelApplet* init(QWidget *parent, const QString& configFile)
    {
        KGlobal::locale()->insertCatalogue("kweather");
        kweather *theApplet = new kweather(configFile, KPanelApplet::Normal,
                KPanelApplet::About | KPanelApplet::Help | KPanelApplet::Preferences,
                parent, "kweather");
        return theApplet;
    }
}

kweather::kweather(const QString& configFile, Type t, int actions, QWidget *parent, const char *name):
                KPanelApplet(configFile, t, actions, parent, name), weatherIface()
{
	kdDebug(12004) << "Constructor " << endl;
	setObjId("weatherIface");
	firstrun = false;
	loadPrefs();
	
	client = KApplication::kApplication()->dcopClient();
	if(!client->isAttached())
		client->attach();
	if(attach())
		kdDebug(12004) << "attached to the server..." << endl;

	p = new dockwidget(this, "test");
	connect(p, SIGNAL(buttonEvent()), SLOT(getButtonEvent()));
	p->setFont(theFont);
	p->show();

	timeOut = new QTimer(this, "timeOut" );
	timeOut->changeInterval(interval*60000);
	connect(timeOut, SIGNAL(timeout()), this, SLOT(timeout()));
	emit (updateLayout());

	mPrefs = 0L;
	mReport = 0L;

	if (!connectDCOPSignal(0,0, "fileUpdate(QString)",
		"refresh(QString)",false))
		kdDebug(12004) << "Could not attach signal..." << endl;	
	else
		kdDebug(12004) << "attached dcop signals..." << endl;

	if(firstrun)
		preferences();
	else
		timeout();
}

kweather::~kweather()
{
}

/** about box */
void kweather::about(){
    kdDebug(12004) << "Telling about" << endl;
    KAboutData aboutData("KWeather", "KWeather", "2.1.0",
            I18N_NOOP("Weather applet for the Kicker"), KAboutData::License_GPL_V2);
    aboutData.addAuthor("Ian Reinhart Geiser", "", "geiseri@users.sourceforge.net",
            "http://www.kde.org/");
    //aboutData.addAuthor("Nadeem Hasan",  "", "nhasan@nadmm.com", "http://www.nadmm.com/");
    aboutData.addCredit("Will Andrews", I18N_NOOP("Fixed for BSD port"),
            "wca@users.sourceforge.net", "");
    aboutData.addCredit("Ben Burton", I18N_NOOP("Debian fixes"), "benb@acm.org");
    aboutData.addCredit("Otto Bruggeman", I18N_NOOP("Fixed the i18n stuff and"
            " made sure the indentation was consistent :P"), "bruggie@home.nl");
    aboutData.addCredit("Nadeem Hasan", I18N_NOOP("Lots of bugfixes,"
            " improvements and cleanups."), "nhasan@nadmm.com");

    KAboutApplication about(&aboutData, this, 0);
    about.setImage(locate("data", "kweather/sunny.png"));
    about.exec();
}

/** prefs */
void kweather::preferences(){
    kdDebug(12004) << "prefs" << endl;

    if (mPrefs) {
       // Show the user the existing dialog
       mPrefs->show();
       mPrefs->raise();
    }
    else {
       mPrefs = new prefsDialog();
       mPrefs->setReportLocation(reportLocation);
       mPrefs->setLogFile(fileName);
       mPrefs->setUpdateInterval(interval);
       mPrefs->setOffLineMode(offlineMode);
       mPrefs->setSmallView(smallviewMode);
       mPrefs->setFont(theFont);
       mPrefs->setEnableLog(logOn);

       mPrefs->show();
       connect(mPrefs, SIGNAL(okClicked()), this, SLOT(slotPrefsAccepted()));
       connect(mPrefs, SIGNAL(finished()), this, SLOT(slotPrefsFinished()));
   }
}

/** Get the button event from the child widget */
void kweather::getButtonEvent(){
    kdDebug(12004) << "Button was pressed" << endl;
    doReport();
}

/** The help handler */
void kweather::help(){
    kapp->invokeHelp(QString::null, QString::fromLatin1("kweather"));
}

/** Display the current weather report. */
void kweather::doReport(){
    kdDebug(12004) << "Showing out the report" << endl;
	if ( mReport == 0 )
	{
    	mReport = new reportView(reportLocation);

		connect ( mReport, SIGNAL( finished() ), 
				SLOT( slotReportFinished() ) );
	}

	mReport->setTemp(temperature(reportLocation) );
	mReport->setDewPoint(dewPoint(reportLocation) );
	mReport->setRelHumidity( relHumidity(reportLocation));
	mReport->setHeatIndex( heatIndex(reportLocation) );
	mReport->setWindChill( windChill(reportLocation));
	mReport->setWind( wind(reportLocation) );
	mReport->setDate( date(reportLocation) );
	mReport->setPressure( pressure(reportLocation) );
	mReport->setCover( cover(reportLocation) );
	mReport->setWeather( weather(reportLocation) );
	mReport->setWeatherIcon(currentIconString(reportLocation)  );
	mReport->render();

	mReport->show();
	mReport->raise();
}

void kweather::slotReportFinished(){
	mReport->delayedDestruct();
	mReport = 0;
}

/** load the application mPrefs */
void kweather::loadPrefs(){
    kdDebug(12004) << "Loading Prefs" << endl;
    KConfig *kcConfig = config();

    if (!kcConfig->hasGroup ("General Options") )
        firstrun = true;

    kcConfig->setGroup("General Options");
    logOn = kcConfig->readBoolEntry("logging", false);
    fileName = kcConfig->readEntry("log_file_name", "");
    reportLocation = kcConfig->readEntry("report_location", i18n("none"));
    interval = kcConfig->readNumEntry("timout_value", 60);
    offlineMode = kcConfig->readBoolEntry("offline_mode", true);
    smallviewMode = kcConfig->readNumEntry("smallview_mode", 0);
    theFont = kcConfig->readFontEntry("dock_font", new QFont("helvetica", 8, 50));
}

/** Save the application mPrefs. */
void kweather::savePrefs(){
	kdDebug(12004) << "Saving Prefs..." << endl;
	KConfig *kcConfig = config();

	kcConfig->setGroup("General Options");
	kcConfig->writeEntry("logging", logOn);
	kcConfig->writeEntry("report_location", reportLocation);
	kcConfig->writeEntry("timout_value", interval);
	kcConfig->writeEntry("offline_mode", offlineMode);
	kcConfig->writeEntry("smallview_mode", smallviewMode);
	kcConfig->writeEntry("log_file_name", fileName );
	kcConfig->writeEntry("dock_font", theFont);
	kcConfig->sync();
}

void kweather::showWeather()
{
     p->setPressure(pressure(reportLocation));
     p->setWind(wind(reportLocation));
     p->setTemperature(temperature(reportLocation));
     p->setSmall(smallviewMode);
     p->setWeatherIcon(currentIcon(reportLocation));

    p->showWeather();
}

void kweather::writeLogEntry()
{
    // Write data line in the CSV format
    if (logOn && !fileName.isEmpty())
    {
        kdDebug(12004)<< "Try log file:" << fileName << endl;
        QFile logFile(fileName);
        QTextStream logFileStream(&logFile);
        if (logFile.open(IO_Append | IO_ReadWrite))
        {
            logFileStream << date(reportLocation);
            logFileStream << ",";
            logFileStream << wind(reportLocation);
            logFileStream << ",";
            logFileStream << temperature(reportLocation);
            logFileStream << ",";
            logFileStream << pressure(reportLocation);
            logFileStream << ",";
            logFileStream << cover(reportLocation).join(";");
            logFileStream << ",";
            logFileStream << visibility(reportLocation);
            logFileStream << ",";
            logFileStream << weather(reportLocation).join(";");
            logFileStream << endl;
        }
        else
        {
            KMessageBox::sorry( this,
                    i18n("For some reason the log file could not be written to.\n"
                    "Please check to see if your disk is full or if you "
                    "have write access to the location you are trying to "
                    "write to."),
                    i18n("KWeather Error"));
        }
        logFile.close();
    }
}

/** get new data */
void kweather::timeout(){
    kdDebug(12004)<< "Requesting new data for " << reportLocation  << endl;
    timeOut->stop();
    timeOut->start(interval*60000);

    if ( !offlineMode )
    {
        // Make a dcop connection to the weather service and update the UI
	update(reportLocation);
    }
}

int kweather::widthForHeight(int h) const
{
    int w = smallviewMode? h : h*2;
    p->resizeView(w, h);
    return w;
}

int kweather::heightForWidth(int w) const
{
    int h = smallviewMode? w : w*2;
    p->resizeView(w, h);
    return h;
}

void kweather::refresh(QString stationID)
{
	kdDebug() << "refresh " << stationID << endl;
	if( stationID == reportLocation)
	{
		showWeather();
		writeLogEntry();
	}
}

void kweather::slotPrefsAccepted() {
    reportLocation = mPrefs->reportLocation();
    interval = mPrefs->updateInterval();
    fileName = mPrefs->logFile();
    offlineMode = mPrefs->offLineMode();
    smallviewMode = (bool)mPrefs->smallView();
    theFont = mPrefs->font();
    logOn = mPrefs->enableLog();
    emit (updateLayout());
    p->setFont(theFont);

    if (logOn && !fileName.isEmpty())
    {
        QFile logFile(fileName);
        // Open the file, create it if not already exists
        if (logFile.open(IO_ReadWrite))
        {
            if (logFile.size() == 0)
            {
                // Empty file, put the header
                QTextStream logFileStream(&logFile);
                logFileStream << "Date,Wind Speed & Direction,Temperature,Pressure,Cover,Visibility,Current Weather" << endl;
            }
            logFile.close();
        }
        else
        {
            kdDebug(12004) << "There was an error opening the file...." << endl;
            KMessageBox::sorry( this,
                    i18n("For some reason a new log file could not be opened.\n"
                    "Please check to see if your disk is full or if you have "
                    "write access to the location you are trying to write to."),
                    i18n("KWeather Error"));
        }
    }

    timeout();
    savePrefs();
}

void kweather::mousePressEvent(QMouseEvent * ev) {
    if (ev->button() != Qt::RightButton)
      return;

    KPopupMenu *contextMenu = new KPopupMenu(i18n("KWeather - ") + reportLocation, this);
    contextMenu->insertItem(SmallIcon("viewmag"), i18n("Show &Report"), this, SLOT(doReport()));
    contextMenu->insertItem(SmallIcon("reload"), i18n("&Update Now"), this, SLOT(timeout()));
    contextMenu->insertSeparator();
    contextMenu->insertItem(i18n("&About"), this, SLOT(about()));
    contextMenu->insertItem(SmallIcon("configure"), i18n("&Configure KWeather..."), this, SLOT(preferences()));

    contextMenu->exec(QCursor::pos());
    delete contextMenu;
}

void kweather::slotPrefsFinished() {
   mPrefs->delayedDestruct();
   mPrefs = 0L;
}

QString kweather::temperature(QString stationID)
{
	if (attach())
	{
		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "temperature(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				kdDebug() << result << endl;
				return result;
			} 
		}	
		else
			kdDebug() << "failed " << endl;
	}
	return "";
}

QString kweather::dewPoint(QString stationID)
{
	if (attach())
	{
		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "dewPoint(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}	
	}
	return "";
}
QString kweather::relHumidity(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "relitiveHumidity(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}
			
	}
	
	return "";
}
QString kweather::heatIndex(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "heatIndex(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}
	}
	return "";	
}
QString kweather::windChill(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "windChill(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}
	}
	return "";	
}
QString kweather::wind(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "wind(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}
	}
	return "";	
}
QString kweather::pressure(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "pressure(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}	
	}
	return "";
}
QPixmap kweather::currentIcon(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "currentIcon(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QPixmap") 
			{
				QPixmap result;
				reply >> result;
				return result;
			} 
		}	
	}
	return QPixmap();
}
QString kweather::currentIconString(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "currentIconString(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}	
	}
	return "";
}

QString kweather::date(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "date(QString)", data, replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}
			
	}
	return "";
}
QStringList kweather::weather(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "weather(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QStringList") 
			{
				QStringList result;
				reply >> result;
				return result;
			} 
		}
	}
	return "";	

}
QString kweather::visibility(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "visibility(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QString") 
			{
				QString result;
				reply >> result;
				return result;
			} 
		}
	}
	return "";	
}
QStringList kweather::cover(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		if(client->call("KWeatherService", "WeatherService", "cover(QString)", data,replyType, replyData, true))
		{
			QDataStream reply(replyData, IO_ReadOnly);
			if (replyType == "QStringList") 
			{
				QStringList result;
				reply >> result;
				return result;
			} 
		}
	}
	return "";	
}
void kweather::update(QString stationID)
{
	if (attach())
	{

		QCString replyType;
		QByteArray data,replyData;
		QDataStream arg(data, IO_WriteOnly);
		arg << stationID;
		kdDebug() << "Sending update request..." << endl;
		client->send("KWeatherService", "WeatherService", "update(QString)", data);
	}
}
	
bool kweather::attach()
{
               QString error;
                QCString appID;
                kdDebug() << "Looking for dcop service..." << endl;
                if (!client->isApplicationRegistered("KWeatherService"))
                {
                        kdDebug() << "Could not find service so I am starting it..." << endl;
                        if(!KApplication::startServiceByDesktopName("kweatherservice",QStringList(), &error,&appID ))

                        {
                                kdDebug() << "Starting KWeatherService failed with message: " << error << endl;
                                return false;
                        }
			else
			{
				kdDebug () << "Service Started..." << endl;
			}
                }
		else
		{
			kdDebug() << "Found weather service..." << endl;
		}

                return true;
}
#include "kweather.moc"
