/*
 *   This file is part of the KTeaTime application.
 *
 *   Copyright (C) 1998-1999  Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
 *   Copyright (C) 2002-2003  Martin Willers <willers@xm-arts.de>
 *   Copyright (c) 2007       Stefan Böhmann <kde@hilefoks.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 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
#include "toplevel.h"
#include "timeedit.h"
#include "settings.h"
#include "tea.h"

#include <QString>
#include <QAction>
#include <QTimer>
#include <QPainter>
#include <QBrush>
#include <QActionGroup>

#include <KMenu>
#include <KActionCollection>
#include <KHelpMenu>
#include <KPassivePopup>
#include <KGlobalSettings>
#include <KNotification>
#include <KAboutData>

TopLevel::TopLevel(const KAboutData *aboutData, const QString &icon, QWidget *parent) :
    KSystemTrayIcon(loadIcon(icon),parent),
    m_runningTeaTime(0),
    m_nextNotificationTime(0),
    m_icon(loadIcon(icon)),
    m_pix(loadIcon(icon).pixmap(QSize(22, 22)))
{
    QApplication::setQuitOnLastWindowClosed(false);

    KSharedConfigPtr config = KSharedConfig::openConfig();
    KConfigGroup tealistGroup(config, "Tealist");

    if(tealistGroup.exists()) {
        QString key, time;
        for(unsigned index=0; tealistGroup.hasKey(time.sprintf("Tea%d Time", index)) && tealistGroup.hasKey(key.sprintf("Tea%d Name", index)); ++index) {
            if(int temp=(tealistGroup.readEntry(time, QString())).toUInt())
                m_tealist.append(Tea(tealistGroup.readEntry(key, i18n("Unknown Tea")), temp));
        }
    }

    // If the list of teas is empty insert a set of default teas.
    if(m_tealist.isEmpty()) {
        m_tealist.append(Tea(i18n("Black Tea"), 180));
        m_tealist.append(Tea(i18n("Earl Grey"), 300));
        m_tealist.append(Tea(i18n("Fruit Tea"), 480));
    }


    m_teaActionGroup=new QActionGroup(this);

    // build the context menu
    m_stopAct = new QAction("stop", this);
    m_stopAct->setIcon(KIcon("edit-delete"));
    m_stopAct->setText(i18n("&Stop"));
    m_stopAct->setEnabled(false);

    m_confAct = new QAction("configure", this);
    m_confAct->setIcon(KIcon("configure"));
    m_confAct->setText(i18n("&Configure..."));

    m_anonAct = new QAction("anonymous", this);
    m_anonAct->setText(i18n("&Anonymous..."));

    m_exitAct = actionCollection()->action(KStandardAction::name(KStandardAction::Quit));
    m_exitAct->setShortcut(0); // Not sure if it is correct.

    m_helpMenu = new KHelpMenu(0, aboutData, false);


    loadTeaMenuItems();
    contextMenu()->addSeparator();
    contextMenu()->addAction(m_stopAct);
    contextMenu()->addAction(m_anonAct);
    contextMenu()->addSeparator();
    contextMenu()->addAction(m_confAct);
    contextMenu()->addMenu(m_helpMenu->menu());
    contextMenu()->addAction(m_exitAct);


    m_popup = new KPassivePopup();
    m_popup->setAutoDelete(false);

    m_timer = new QTimer(this);

    connect(m_timer, SIGNAL(timeout()), this, SLOT(teaTimeEvent()));
    connect(m_stopAct, SIGNAL(triggered(bool)), this, SLOT(cancelTea()));
    connect(m_confAct, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog()));
    connect(m_anonAct, SIGNAL(triggered(bool)), this, SLOT(showTimeEditDialog()));
    connect(contextMenu(), SIGNAL(triggered(QAction*)), this, SLOT(runTea(QAction*)));
    connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(showPopup(QSystemTrayIcon::ActivationReason)));

    loadConfig();
    checkState();
}


TopLevel::~TopLevel()
{
    delete m_helpMenu;
    delete m_timer;
    delete m_popup;
    delete m_teaActionGroup;
}


void TopLevel::checkState() {
    bool state=m_runningTeaTime!=0;
    m_teaActionGroup->setEnabled(!state);
    m_stopAct->setEnabled(state);
    m_anonAct->setEnabled(!state);

    if(!state) {
        m_popup->setView(i18n("The Tea Cooker"), i18n("No steeping tea."), m_pix);
        setToolTip(i18n("The Tea Cooker"));
    }
}


void TopLevel::setTeaList(QList<Tea> tealist) {
    m_tealist=tealist;

    // Save list...
    KSharedConfigPtr config = KSharedConfig::openConfig();
    KConfigGroup tealistGroup(config, "Tealist");

    for(int i=0; i<m_tealist.size(); ++i) {
        tealistGroup.writeEntry(QString("Tea%1 Time").arg(i), m_tealist.at(i).time());
        tealistGroup.writeEntry(QString("Tea%1 Name").arg(i), m_tealist.at(i).name());
    }
    tealistGroup.config()->sync();


    foreach(QAction* a, m_teaActionGroup->actions()) {
        m_teaActionGroup->removeAction(a);
    }

    contextMenu()->clear();

    (static_cast<KMenu*>(contextMenu()))->addTitle( qApp->windowIcon(), KGlobal::caption() );

    loadTeaMenuItems();
    contextMenu()->addSeparator();
    contextMenu()->addAction(m_stopAct);
    contextMenu()->addAction(m_anonAct);
    contextMenu()->addSeparator();
    contextMenu()->addAction(m_confAct);
    contextMenu()->addMenu(m_helpMenu->menu());
    contextMenu()->addAction(m_exitAct);

    loadConfig();
}


void TopLevel::loadTeaMenuItems() {
    int i=0;
    foreach(const Tea &t, m_tealist) {
        QString s;
        s = i18nc("%1 - name of the tea, %2 - the predefined time for the tea", "%1 (%2)", t.name(),t.timeToString()); 
        QAction *a=contextMenu()->addAction(s);
        a->setData(++i);
        m_teaActionGroup->addAction(a);
    }
}


void TopLevel::showSettingsDialog()
{
    SettingsDialog(this, m_tealist).exec();
}


void TopLevel::showTimeEditDialog()
{
    TimeEditDialog(this).exec();
}


void TopLevel::runTea(QAction *a)
{
    int index=a->data().toInt();
    if(index<=0)
        return;
    --index;

    if(index>m_tealist.size())
        return;

    runTea(m_tealist.at(index));
}


void TopLevel::runTea(Tea tea)
{
    m_runningTea=tea;
    m_runningTeaTime=m_runningTea.time();
    checkState();
    repaintTrayIcon();
    m_timer->start(1000);
}


void TopLevel::repaintTrayIcon()
{
     m_pix=m_icon.pixmap(QSize(22, 22));
    if(m_runningTeaTime==0) {
        setIcon(m_icon);
    } else {
        QPainter p(&m_pix);
        p.setRenderHint (QPainter::Antialiasing);

        p.setBrush(QBrush(QColor(0,255,0, 190)));
        QRectF rectangle(2, geometry().height()-12, 10, 10);
        p.drawPie(rectangle, 90*16, 360*16);

        if(m_runningTeaTime>0) {
            p.setBrush(QColor(255, 0, 0, 190));
            p.drawPie(rectangle, 90*16, -(360*16/m_runningTea.time()*m_runningTeaTime) );
        }
        else if((m_runningTeaTime*-1)%2==0) {
           p.setBrush(QColor(255, 0, 0, 190));
           p.drawPie(rectangle, 90*16, -360*16);
        }
        setIcon(m_pix);
    }
}


void TopLevel::teaTimeEvent()
{
    QString title=i18n("The Tea Cooker");

    if(m_runningTeaTime==0) {
        m_timer->stop();

        QString content=i18n("%1 is now ready!", m_runningTea.name());

        //NOTICE Timeout is set to ~24 days when no auto hide is request. Ok - nearly the same...
        if(m_usepopup)
            showMessage( title, content, QSystemTrayIcon::Information, m_autohide ? m_autohidetime*1000 : 2100000000 );

        if(m_usenotification)
            KNotification::event( "ready", content, m_pix );


        if(m_usereminder && m_remindertime>0) {
            m_popup->setView(title,  content, m_pix);
            setToolTip(content);
            m_timer->start(1000);
            m_nextNotificationTime-=m_remindertime;
            --m_runningTeaTime;
        }
        checkState();
    }
    else if(m_runningTeaTime<0) {
        QString content=i18n("%1 is ready since %2!", m_runningTea.name(), Tea::int2time(m_runningTeaTime*-1, true) );
        setToolTip(content);
        m_popup->setView(title, content, m_pix);

        if(m_runningTeaTime==m_nextNotificationTime) {
            showMessage( title, content, QSystemTrayIcon::Information, m_autohide ? m_autohidetime*1000 : 2100000000 );
	    KNotification::event( "reminder", content, m_pix);
            m_nextNotificationTime-=m_remindertime;
        }
        --m_runningTeaTime;
    }
    else {
        --m_runningTeaTime;
        setToolTip(i18nc("%1 is the time, %2 is the name of the tea", "%1 left for %2.", Tea::int2time(m_runningTeaTime, true), m_runningTea.name()));
        m_popup->setView(title, i18nc("%1 is the time, %2 is the name of the tea", "%1 left for %2.", Tea::int2time(m_runningTeaTime, true), m_runningTea.name()), m_pix);
    }

    if(m_usevisualize)
        repaintTrayIcon();
}


void TopLevel::cancelTea()
{
    m_timer->stop();
    m_runningTeaTime=0;
    checkState();
    if(m_usevisualize)
        repaintTrayIcon();
}


void TopLevel::loadConfig()
{
    KSharedConfigPtr config = KSharedConfig::openConfig();
    KConfigGroup generalGroup(config, "General");

    m_usenotification=generalGroup.readEntry("UseNotification", true);
    m_usepopup=generalGroup.readEntry("UsePopup", true);
    m_autohide=generalGroup.readEntry("PopupAutoHide", false);
    m_autohidetime=generalGroup.readEntry("PopupAutoHideTime", 30);
    m_usereminder=generalGroup.readEntry("UseReminder", false);
    m_remindertime=generalGroup.readEntry("ReminderTime", 60);
    m_usevisualize=generalGroup.readEntry("UseVisualize", true);
}


void TopLevel::showPopup(QSystemTrayIcon::ActivationReason reason)
{
    if(reason==QSystemTrayIcon::Context) {
        m_popup->setVisible(false);
    }
    else if(reason==QSystemTrayIcon::Trigger || reason==QSystemTrayIcon::DoubleClick) {
        if(m_popup->isVisible())
            m_popup->setVisible(false);
        else
            m_popup->show(calculatePopupPoint());
    }
}


QPoint TopLevel::calculatePopupPoint()
{
    QPoint pos=geometry().topLeft();

    int x=pos.x();
    int y=pos.y();
    int w=m_popup->minimumSizeHint().width();
    int h=m_popup->minimumSizeHint().height();

    QRect r=KGlobalSettings::desktopGeometry(QPoint(x+w/2,y+h/2));

    if(x<r.center().x())
        x+=geometry().width();
    else
        x-=w;

    if((y+h)>r.bottom())
        y=r.bottom()-h;

    if((x+w)>r.right())
        x=r.right()-w;

    if(y<r.top())
        y=r.top();

    if(x<r.left())
        x=r.left();

    return QPoint(x,y);
}

