/*
 *   Copyright (C) 2007 Ryan P. Bitanga <ephebiphobic@gmail.com>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License version 2 as
 *   published by the Free Software Foundation
 *
 *   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 Library 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 "spellcheck.h"

#include <QClipboard>

#include <KApplication>
// #include <KDebug>
#include <KGlobal>
#include <KIcon>

SpellCheckRunner::SpellCheckRunner(QObject* parent, const QVariantList &args)
    : Plasma::AbstractRunner(parent, args)
{
    Q_UNUSED(args)
    KGlobal::locale()->insertCatalog(QLatin1String( "krunner_spellcheckrunner" ));
    setObjectName(QLatin1String( "Spell Checker" ));
    setIgnoredTypes(Plasma::RunnerContext::FileSystem | Plasma::RunnerContext::NetworkLocation);
    setSpeed(AbstractRunner::SlowSpeed);
}

SpellCheckRunner::~SpellCheckRunner()
{
}

void SpellCheckRunner::init()
{
    Plasma::AbstractRunner::init();

    //store all language names, makes it posible to type "spell german TERM" if english locale is set
    KLocale *locale = KGlobal::locale();
    QStringList codes = locale->allLanguagesList();
    foreach (const QString &code, codes) {
        const QString name = locale->languageCodeToName(code);
        m_languages[name.toLower()] = code;
    }
}

void SpellCheckRunner::reloadConfiguration()
{
    m_triggerWord = config().readEntry("trigger", i18n("spell"));
    //Processing will be triggered by "keyword "
    m_triggerWord += QLatin1Char( ' ' );

    m_requireTriggerWord = config().readEntry("requireTriggerWord", true);

    Plasma::RunnerSyntax s(i18nc("Spelling checking runner syntax, first word is trigger word, e.g.  \"spell\".",
                                 "%1:q:", m_triggerWord),
                           i18n("Checks the spelling of :q:."));

    if (!m_requireTriggerWord) {
        s.addExampleQuery(QLatin1String( ":q:" ));
    }

    QList<Plasma::RunnerSyntax> syns;
    syns << s;
    setSyntaxes(syns);
}

void SpellCheckRunner::match(Plasma::RunnerContext &context)
{
    if (!context.isValid()) {
        return;
    }


    const QString term = context.query();
    QString query = term;

    if (m_requireTriggerWord) {
        int len = m_triggerWord.length();
        if (query.left(len) != m_triggerWord) {
            return;
        }

        QString language = m_speller.defaultLanguage();
        query = query.mid(len).trimmed();
        QStringList terms = query.split(' ');

        //two terms specified, check if first is a language
        QString customLanguage;
        if (terms.count() == 2) {
            customLanguage = terms[0];
            query = terms[1];
        }
        //three terms specified, check if first two are a language, e.g. "american english"
        if (terms.count() == 3) {
            customLanguage = terms[0] + ' ' + terms[1];
            query = terms[2];
        }

        if (!customLanguage.isEmpty()) {
            language = customLanguage;
            m_speller.setLanguage(language);

            //not valid, maybe it is a language name, not a code
            if (!m_speller.isValid()) {
                QHash<QString, QString>::const_iterator it = m_languages.constFind(language.toLower());
                //is a valid language name
                if (it != m_languages.constEnd()) {
                    language = *it;
                }
            }
        }

        m_speller.setLanguage(language);
    }

    if (query.size() < 3) {
        return;
    }

    Plasma::QueryMatch match(this);
    match.setType(Plasma::QueryMatch::InformationalMatch);

    if (m_speller.isValid()) {
        QStringList suggestions;
        const bool correct = m_speller.checkAndSuggest(query,suggestions);
        if (correct) {
            match.setIcon(KIcon(QLatin1String( "checkbox" )));
            match.setText(i18n("Correct"));
        } else {
            match.setIcon(KIcon(QLatin1String( "edit-delete" )));
            const QString recommended = i18n("Suggested words: %1", suggestions.join(i18nc("seperator for a list of words", ", ")));
            //TODO: try setting a text and a subtext, with the subtext being the suggestions
            match.setText(recommended);
            match.setData(suggestions);
        }
    } else {
        match.setIcon(KIcon(QLatin1String("task-attention")));
        match.setText(i18n("Could not find a dictionary."));
    }

    context.addMatch(term, match);
}

void SpellCheckRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
{
    Q_UNUSED(context)
    //Copy words to clipboard
    kapp->clipboard()->setText(match.data().toString());
}

#include "spellcheck.moc"
