/***************************************************************************
                          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 <kaboutdata.h>
#include <kaboutapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include "reportview.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)
                #ifdef dcop_iface
                ,DCOPObject("weatherIface")
                #endif

{
    kdDebug() << "Constructor " << endl;
    firstrun = false;
    loadPrefs();

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

    weather = new weatherlib(reportLocation);
    kdDebug() << "Setting Timer..." << endl;
    timeOut = new QTimer(this, "timeOut" );
    timeOut->changeInterval(interval*60000);
    connect(timeOut, SIGNAL(timeout()), this, SLOT(timeout()));
#ifdef dcop_iface
    theClient = new DCOPClient();
    theClient->registerAs(name);
#endif
    emit (updateLayout());
    if(firstrun)
        preferences();
    else
        timeout();
}

kweather::~kweather()
{
}

/** about box */
void kweather::about(){
    kdDebug() << "Telling about" << endl;
    KAboutData *aboutData = new KAboutData("KWeather", "KWeather", "2.0.1",
            I18N_NOOP("Weather Applet for the kicker"), KAboutData::License_GPL_V2);
    aboutData->addAuthor("Ian Reinhart Geiser", "", "geiseri@users.sourceforge.net",
            "http://kweather.sourceforge.net/");
    aboutData->addCredit("Will Andrews", I18N_NOOP("Fixed for BSD port"),
            "wca@users.sourceforge.net", "http://kweather.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@kde.org");

    KAboutApplication *about = new KAboutApplication(aboutData);
    about->setImage(locate("data", "kweather/sunny.png"));
    about->exec();

    delete(about);
    delete(aboutData);
}

/** prefs */
void kweather::preferences(){
    kdDebug() << "prefs" << endl;
    prefsDialog *prefs = new prefsDialog();
    prefs->setLocation(reportLocation);
    prefs->setFileName(fileName);
    prefs->setGMTOffset(gmtOffset);
    prefs->setTimeValue(interval);
    prefs->setMetricMode(metricMode);
    prefs->setOffLineMode(offlineMode);
    prefs->setSmallView(smallviewMode);
    prefs->setFont(theFont);
    prefs->setLoggingEnabled(logOn);

    // Make sure the logfile box is correctly enabled/disabled
    prefs->enableLogFile(logOn);

    if (prefs->exec())
    {
        timeOut->stop();
        kdDebug() << prefs->getReportLocation() << endl;
        kdDebug() << prefs->getGMTOffset() << endl;
        kdDebug() << prefs->getTimeValue() << endl;
        kdDebug() << prefs->getFileName() << endl;
        kdDebug() << prefs->getMetricMode() << endl;
        kdDebug() << prefs->getOffLineMode() << endl;
        reportLocation = prefs->getReportLocation();
        gmtOffset = (prefs->getGMTOffset()).toInt();
        interval = prefs->getTimeValue();
        fileName = prefs->getFileName();
        metricMode = prefs->getMetricMode();
        offlineMode = prefs->getOffLineMode();
        smallviewMode = (bool)prefs->getSmallView();
        theFont = prefs->getFont();
        logOn = prefs->getLoggingEnabled();
        emit (updateLayout());
        p->setFont(theFont);
        timeOut->start(100);

        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()<< "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:"));
            }
        }
    }
    delete prefs;
    savePrefs();
}

/** Get the button event from the child widget */
void kweather::getButtonEvent(){
    kdDebug() << "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() << "Printing out the report" << endl;
    reportView *theReport = new reportView(0, "Current Weather Report");
    theReport->setTemp(weather->temp());
    theReport->setPressure(weather->pressure());
    theReport->setWind(weather->wind());
    theReport->setDate(weather->date(gmtOffset));
    theReport->setCover(weather->cover());
    theReport->setWeather(weather->weather());
    theReport->setWeatherIcon(weather->currentIcon());
    theReport->render();

    if (theReport->exec())
        delete theReport;
}

/** load the application prefs */
void kweather::loadPrefs(){
    kdDebug() << "Loading Prefs" << endl;
    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", "none");
    gmtOffset = kcConfig->readNumEntry("gmt_offset", 0);
    interval = kcConfig->readNumEntry("timout_value", 60);
    metricMode = kcConfig->readBoolEntry("metric_mode", false);
    offlineMode = kcConfig->readBoolEntry("offline_mode", false);
    smallviewMode = kcConfig->readNumEntry("smallview_mode", 0);
    theFont = kcConfig->readFontEntry("dock_font", new QFont("helvetica", 8, 50));
}

/** Save the application prefs. */
void kweather::savePrefs(){
    kdDebug() << "Saving Prefs..." << endl;
    kcConfig->setGroup("General Options");
    kcConfig->writeEntry( "logging", logOn);
    kcConfig->writeEntry( "report_location", reportLocation);
    kcConfig->writeEntry( "gmt_offset", gmtOffset);
    kcConfig->writeEntry( "timout_value", interval);
    kcConfig->writeEntry( "metric_mode", metricMode);
    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::downloadData( KIO::Job *, const QByteArray &data)
{
    metarData += data;
}

void kweather::parseWeather(QString metarData, bool metricMode)
{
    weather->processData(metarData, metricMode);
    p->setPressure(weather->pressure());
    p->setWind(weather->wind());
    p->setTemperature(weather->temp());
    p->setSmall(smallviewMode);
    p->setWeatherIcon(weather->currentIcon());

    p->showWeather();

    writeLogEntry();
}

void kweather::writeLogEntry()
{
    // Write data line in the CSV format
    if (logOn && !fileName.isEmpty())
    {
        kdDebug()<< "Try log file:" << fileName << endl;
        QFile logFile(fileName);
        QTextStream logFileStream(&logFile);
        if (logFile.open(IO_Append | IO_ReadWrite))
        {
            logFileStream << weather->date(gmtOffset);
            logFileStream << ",";
            logFileStream << weather->wind();
            logFileStream << ",";
            logFileStream << weather->temp();
            logFileStream << ",";
            logFileStream << weather->pressure();
            logFileStream << ",";
            logFileStream << weather->cover().join(";");
            logFileStream << ",";
            logFileStream << weather->visibility();
            logFileStream << ",";
            logFileStream << weather->weather().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();
    }
}

/** Load the data into the current memory */
void kweather::loadFile( KIO::Job *aJob)
{
    // data
    if (!aJob->error())
        parseWeather(metarData, metricMode);

    kdDebug() << "Finished loadfile, restarting the clock" << endl;
    timeOut->start(interval*60000);
}

/** get new data */
void kweather::timeout(){
    kdDebug()<< "Times up..." << endl;
    timeOut->stop();
    QString url;

    if ( !offlineMode )
    {
        //url = "ftp://weather.noaa.gov/data/observations/metar/stations/";
        url = "http://weather.noaa.gov/pub/data/observations/metar/stations/";
        url += reportLocation.upper().stripWhiteSpace();
        url += ".TXT";
        metarData = QString::null;
        theJob = KIO::get(url, true, false);
        connect(theJob, SIGNAL(data(KIO::Job *, const QByteArray &)), SLOT(downloadData(KIO::Job *, const QByteArray &)));
        connect( theJob, SIGNAL( result( KIO::Job *)), this, SLOT( loadFile( KIO::Job *)));
    }
}

int kweather::widthForHeight(int h) const
{
    kdDebug() << "W4H Resize: " << h << endl;
    kdDebug() << "Icon Mode: " << smallviewMode << endl;

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

int kweather::heightForWidth(int w) const
{
    kdDebug() << "H4W Resize: " << w << endl;
    kdDebug() << "Icon Mode: " << smallviewMode << endl;

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

/** This will return the current temperature.  This is only meant to be used through the DCOP interface. */
QString kweather::get_temperature(){
    kdDebug()<< "Getting Temp" << endl;
    return weather->temp();
}

/** This will return the current pressure. This is only meant for the DCOP interface */
QString kweather::get_pressure(){
    kdDebug()<< "Getting Pressure" << endl;
    return weather->pressure();
}

/** return wind info */
QString kweather::get_wind(){
    return weather->wind();
}

/** return current weather */
QString kweather::get_weather(){
    return weather->weather().join(",") + "," + weather->cover().join(",");
}

void kweather::refresh()
{
    timeout();
}
#include "kweather.moc"
