/***************************************************************************
 *   Copyright (C) 2005, 2006 by Pino Toscano, toscano.pino@tiscali.it     *
 *                                                                         *
 *   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 "kalziumschemetype.h"

#include "kalziumdataobject.h"
#include "prefs.h"

#ifdef HAVE_OPENBABEL2
#include <openbabel/mol.h>
#endif

#include <QBrush>

#include <klocale.h>
#include <QDebug>
#include <QStandardPaths>



KalziumSchemeTypeFactory::KalziumSchemeTypeFactory()
{
    m_schemes << KalziumMonoColorSchemeType::instance();
    m_schemes << KalziumBlocksSchemeType::instance();
    m_schemes << KalziumIconicSchemeType::instance();
    m_schemes << KalziumFamilySchemeType::instance();
    m_schemes << KalziumGroupsSchemeType::instance();
    #ifdef HAVE_OPENBABEL2
    m_schemes << KalziumColorSchemeType::instance();
    #endif
}

KalziumSchemeTypeFactory* KalziumSchemeTypeFactory::instance()
{
    static KalziumSchemeTypeFactory kstf;
    return &kstf;
}

KalziumSchemeType* KalziumSchemeTypeFactory::build(int id) const
{
    if ((id < 0) || (id >= m_schemes.count())) {
        return 0;
    }

    return m_schemes.at(id);
}

KalziumSchemeType* KalziumSchemeTypeFactory::build(const QByteArray& id) const
{
    for (int i = 0; i < m_schemes.count(); ++i) {
        if (m_schemes.at(i)->name() == id) {
            return m_schemes.at(i);
        }
    }

    return 0;
}

QStringList KalziumSchemeTypeFactory::schemes() const
{
    QStringList l;
    for (int i = 0; i < m_schemes.count(); ++i) {
        l << m_schemes.at(i)->description();
    }
    return l;
}


KalziumSchemeType* KalziumSchemeType::instance()
{
    return 0;
}

KalziumSchemeType::KalziumSchemeType()
{

}

KalziumSchemeType::~KalziumSchemeType()
{
}

KalziumMonoColorSchemeType::KalziumMonoColorSchemeType()
        : KalziumSchemeType()
{
}

KalziumMonoColorSchemeType* KalziumMonoColorSchemeType::instance()
{
    static KalziumMonoColorSchemeType kmcst;
    return &kmcst;
}

QByteArray KalziumMonoColorSchemeType::name() const
{
    return "MonoColor";
}

QString KalziumMonoColorSchemeType::description() const
{
    return i18n("Monochrome");
}

QBrush KalziumMonoColorSchemeType::elementBrush(int el) const
{
    Q_UNUSED(el);
    return QBrush(Prefs::noscheme());
}

QColor KalziumMonoColorSchemeType::textColor(int el) const
{
    Q_UNUSED(el);
    return Qt::black;
}

QList<legendPair> KalziumMonoColorSchemeType::legendItems() const
{
    QList<legendPair> ll;
    ll << qMakePair(i18n("All the Elements"), QColor(Prefs::noscheme()));
    return ll;
}


KalziumBlocksSchemeType::KalziumBlocksSchemeType()
        : KalziumSchemeType()
{
}

KalziumBlocksSchemeType* KalziumBlocksSchemeType::instance()
{
    static KalziumBlocksSchemeType kbst;
    return &kbst;
}

QByteArray KalziumBlocksSchemeType::name() const
{
    return "Blocks";
}

QString KalziumBlocksSchemeType::description() const
{
    return i18n("Blocks");
}

QBrush KalziumBlocksSchemeType::elementBrush(int el) const
{
    QString block = KalziumDataObject::instance()->element(el)->dataAsString(ChemicalDataObject::periodTableBlock);

    QColor c;
    if (block == QLatin1String("s")) {
        c = Prefs::block_s();
    } else if (block == QLatin1String("p")) {
        c = Prefs::block_p();
    } else if (block == QLatin1String("d")) {
        c = Prefs::block_d();
    } else if (block == QLatin1String("f")) {
        c = Prefs::block_f();
    } else {
        c = Qt::lightGray;
    }

    return QBrush(c);
}

QColor KalziumBlocksSchemeType::textColor(int el) const
{
    Q_UNUSED(el);
    return Qt::black;
}

QList<legendPair> KalziumBlocksSchemeType::legendItems() const
{
    QList<legendPair> ll;
    ll << qMakePair(i18n("s-Block"), QColor(Prefs::block_s()));
    ll << qMakePair(i18n("p-Block"), QColor(Prefs::block_p()));
    ll << qMakePair(i18n("d-Block"), QColor(Prefs::block_d()));
    ll << qMakePair(i18n("f-Block"), QColor(Prefs::block_f()));
    return ll;
}

///ICONIC SCHEME///

KalziumIconicSchemeType::KalziumIconicSchemeType()
        : KalziumSchemeType()
{
}

KalziumIconicSchemeType* KalziumIconicSchemeType::instance()
{
    static KalziumIconicSchemeType kist;
    return &kist;
}

QByteArray KalziumIconicSchemeType::name() const
{
    return "Iconic";
}

QString KalziumIconicSchemeType::description() const
{
    return i18n("Iconic");
}

QBrush KalziumIconicSchemeType::elementBrush(int el) const
{
    QPixmap pixmap = KalziumDataObject::instance()->pixmap(el);
    return QBrush(pixmap);
}

QColor KalziumIconicSchemeType::textColor(int) const
{
    return Qt::transparent;
}

QList<legendPair> KalziumIconicSchemeType::legendItems() const
{
    QList<legendPair> ll;
    ll << qMakePair(i18n("Each element is represented by an icon which represents its use."), QColor());
    return ll;
}


///Family///
KalziumFamilySchemeType::KalziumFamilySchemeType()
        : KalziumSchemeType()
{
}

KalziumFamilySchemeType* KalziumFamilySchemeType::instance()
{
    static KalziumFamilySchemeType kbst;
    return &kbst;
}

QByteArray KalziumFamilySchemeType::name() const
{
    return "Family";
}

QString KalziumFamilySchemeType::description() const
{
    return i18n("Family");
}

QBrush KalziumFamilySchemeType::elementBrush(int el) const
{
    QString family = KalziumDataObject::instance()->element(el)->dataAsString(ChemicalDataObject::family);

    QColor c;

    if (family == QLatin1String("Noblegas")) {
        c = Prefs::noble_gas();
    } else if (family == QLatin1String("Non-Metal")) {
        c = Prefs::nonmetal();
    } else if (family == QLatin1String("Rare_Earth")) {
        c = Prefs::rare();
    } else if (family == QLatin1String("Alkaline_Earth")) {
        c = Prefs::alkaline();
    } else if (family == QLatin1String("Alkali_Earth")) {
        c = Prefs::alkalie();
    } else if (family == QLatin1String("Transition")) {
        c = Prefs::transition();
    } else if (family == QLatin1String("Other_Metal")) {
        c = Prefs::other_metal();
    } else if (family == QLatin1String("Metalloids")) {
        c = Prefs::metalloid();
    } else if (family == QLatin1String("Halogen")) {
        c = Prefs::halogene();
    } else {
        c = Qt::lightGray;
    }

    return QBrush(c);
}

QColor KalziumFamilySchemeType::textColor(int) const
{
    return Qt::black;
}

QList<legendPair> KalziumFamilySchemeType::legendItems() const
{
    QList<legendPair> ll;
    ll << qMakePair(i18n("Alkaline"),QColor(Prefs::alkalie()));
    ll << qMakePair(i18n("Rare Earth"),QColor(Prefs::rare()));
    ll << qMakePair(i18n("Non-Metals"),QColor(Prefs::nonmetal()));
    ll << qMakePair(i18n("Alkalie Metal"),QColor(Prefs::alkaline()));
    ll << qMakePair(i18n("Other Metal"),QColor(Prefs::other_metal()));
    ll << qMakePair(i18n("Halogen"),QColor(Prefs::halogene()));
    ll << qMakePair(i18n("Transition Metal"),QColor(Prefs::transition()));
    ll << qMakePair(i18n("Noble Gas"),QColor(Prefs::noble_gas()));
    ll << qMakePair(i18n("Metalloid"),QColor(Prefs::metalloid()));

    return ll;
}

///GROUPS///
KalziumGroupsSchemeType::KalziumGroupsSchemeType()
        : KalziumSchemeType()
{
}

KalziumGroupsSchemeType* KalziumGroupsSchemeType::instance()
{
    static KalziumGroupsSchemeType kbst;
    return &kbst;
}

QByteArray KalziumGroupsSchemeType::name() const
{
    return "Groups";
}

QString KalziumGroupsSchemeType::description() const
{
    return i18n("Groups");
}

QBrush KalziumGroupsSchemeType::elementBrush(int el) const
{
    QString group = KalziumDataObject::instance()->element(el)->dataAsString(ChemicalDataObject::group);

    QColor c;

    if (group == QLatin1String("1")) {
        c = Prefs::group_1();
    } else if (group == QLatin1String("2")) {
        c = Prefs::group_2();
    } else if (group == QLatin1String("3")) {
        c = Prefs::group_3();
    } else if (group == QLatin1String("4")) {
        c = Prefs::group_4();
    } else if (group == QLatin1String("5")) {
        c = Prefs::group_5();
    } else if (group == QLatin1String("6")) {
        c = Prefs::group_6();
    } else if (group == QLatin1String("7")) {
        c = Prefs::group_7();
    } else if (group == QLatin1String("8")) {
        c = Prefs::group_8();
    } else {
        c = Qt::lightGray;
    }

    return QBrush(c);
}

QColor KalziumGroupsSchemeType::textColor(int) const
{
    return Qt::black;
}

QList<legendPair> KalziumGroupsSchemeType::legendItems() const
{
    QList<legendPair> ll;
    ll << qMakePair(i18n("Group 1"), QColor(Prefs::group_1()));
    ll << qMakePair(i18n("Group 2"), QColor(Prefs::group_2()));
    ll << qMakePair(i18n("Group 3"), QColor(Prefs::group_3()));
    ll << qMakePair(i18n("Group 4"), QColor(Prefs::group_4()));
    ll << qMakePair(i18n("Group 5"), QColor(Prefs::group_5()));
    ll << qMakePair(i18n("Group 6"), QColor(Prefs::group_6()));
    ll << qMakePair(i18n("Group 7"), QColor(Prefs::group_7()));
    ll << qMakePair(i18n("Group 8"), QColor(Prefs::group_8()));

    return ll;
}

#ifdef HAVE_OPENBABEL2
///OpenBabel Color///
KalziumColorSchemeType::KalziumColorSchemeType()
        : KalziumSchemeType()
{
}

KalziumColorSchemeType* KalziumColorSchemeType::instance()
{
    static KalziumColorSchemeType kbst;
    return &kbst;
}

QByteArray KalziumColorSchemeType::name() const
{
    return "Color";
}

QString KalziumColorSchemeType::description() const
{
    return i18n("Colors");
}

QBrush KalziumColorSchemeType::elementBrush(int el) const
{
    QColor c;

    std::vector<double> color = OpenBabel::etab.GetRGB(el);
    c.setRgbF(color[0], color[1], color[2]);

    return QBrush(c);
}

QColor KalziumColorSchemeType::textColor(int) const
{
    return Qt::black;
}

QList<legendPair> KalziumColorSchemeType::legendItems() const
{
    QList<legendPair> ll;
    ll << qMakePair(i18n("Nice colors without meaning. (From the Openbabel project)"), QColor());
    return ll;
}
#endif


///CRYSTAL///
//X KalziumCrystalSchemeType::KalziumCrystalSchemeType()
//X   : KalziumSchemeType()
//X {
//X }
//X
//X KalziumCrystalSchemeType* KalziumCrystalSchemeType::instance()
//X {
//X     static KalziumCrystalSchemeType kbst;
//X     return &kbst;
//X }
//X
//X QByteArray KalziumCrystalSchemeType::name() const
//X {
//X     return "Crystal";
//X }
//X
//X QString KalziumCrystalSchemeType::description() const
//X {
//X     return i18n("Crystal Structures");
//X }
//X
//X QBrush KalziumCrystalSchemeType::elementBrush(int el, const QRect& elrect) const
//X {
//X     QString crystal = KalziumDataObject::instance()->element(el)->dataAsString(ChemicalDataObject::crystalstructure);
//X
//X     qDebug() << "crystal is " << crystal;
//X
//X     static QString resourcepath;
//X     if (resourcepath.isEmpty()) {
//X         resourcepath = QStandardPaths::locate(QStandardPaths::DataLocation, "data/latticeicons/");
//X     }
//X
//X     QString filename;
//X     if (crystal == "bcc") {
//X         filename = "ci.png";
//X     } else if (crystal == "ccp") {
//X         filename = "cp.png";
//X     } else if (crystal ==  "fcc") {
//X         filename = "cf.png";
//X     } else if (crystal ==  "hcp") {
//X         filename = "hp.png";
//X     } else if (crystal ==  "rh") {
//X         filename = "hr.png";//Rhombohedral primitive
//X     } else if (crystal ==  "or") {
//X         filename = "op.png";//Orthorhombic primitive
//X     } else if (crystal ==  "mono") {
//X         filename = "ms.png";//Monoclinic primitive
//X     } else if (crystal ==  "tri") {
//X         filename = "ap.png";//Triclinic
//X     } else if (crystal ==  "tp") {
//X         filename = "tp.png";//Tetragonal primitive
//X     }
//X
//X         filename.prepend(resourcepath);
//X
//X     QBrush ret;
//X     if (!filename.isEmpty()) {
//X         qDebug() << el << ": FILENAME is not EMPTY... " << filename;
//X         QPixmap pixmap(resourcepath + filename);
//X         ret = QBrush(pixmap.scaled(elrect.size(), Qt::KeepAspectRatio));
//X     } else {
//X             qDebug() << el << ": FILENAME EMPTY... " << filename;
//X         ret.setColor(Qt::gray);
//X     }
//X
//X     return ret;
//X }
//X
//X QColor KalziumCrystalSchemeType::textColor(int) const
//X {
//X     return Qt::black;
//X }
//X
//X QList<legendPair> KalziumCrystalSchemeType::legendItems() const
//X {
//X     static QString resourcepath;
//X     if (resourcepath.isEmpty())
//X     {
//X         resourcepath = QStandardPaths::locate(QStandardPaths::DataLocation, "data/latticeicons/");
//X     }
//X
//X     QList<legendPair> ll;
//X     ll << qMakePair(i18n("bcc, body centered cubic"), QColor(QPixmap(resourcepath + "ci.png")));
//X     ll << qMakePair(i18n("ccp, cubic close packed"), QColor(QPixmap(resourcepath + "cp.png")));
//X     ll << qMakePair(i18n("fcc, face centered cubic"), QColor(QPixmap(resourcepath + "cf.png")));
//X     ll << qMakePair(i18n("hcp, hexagonal close packed"), QColor(QPixmap(resourcepath + "hp.png")));
//X     ll << qMakePair(i18n("rh, rhombohedral"), QColor(QPixmap(resourcepath + "hr.png")));
//X     ll << qMakePair(i18n("or, orthorhombic primitive"), QColor(QPixmap(resourcepath + "op.png")));
//X     ll << qMakePair(i18n("ms, monoclinic"), QColor(QPixmap(resourcepath + "ms.png")));
//X     ll << qMakePair(i18n("ap, triclinic"), QColor(QPixmap(resourcepath + "ap.png")));
//X     ll << qMakePair(i18n("tp, tetragonal primitive"), QColor(QPixmap(resourcepath + "tp.png")));
//X
//X     return ll;
//X }

////
//X KalziumDiscoverymapSchemeType::KalziumDiscoverymapSchemeType()
//X   : KalziumSchemeType()
//X {
//X }
//X
//X KalziumDiscoverymapSchemeType* KalziumDiscoverymapSchemeType::instance()
//X {
//X     static KalziumDiscoverymapSchemeType kbst;
//X     return &kbst;
//X }
//X
//X QByteArray KalziumDiscoverymapSchemeType::name() const
//X {
//X     return "Crystal";
//X }
//X
//X QString KalziumDiscoverymapSchemeType::description() const
//X {
//X     return i18n("Discovery Country");
//X }
//X
//X QBrush KalziumDiscoverymapSchemeType::elementBrush(int el, const QRect& elrect) const
//X {
//X     QString map = KalziumDataObject::instance()->element(el)->dataAsString(ChemicalDataObject::discoveryCountry);
//X
//X     static QString resourcepath;
//X     if (resourcepath.isEmpty()) {
//X         resourcepath = QStandardPaths::locate(QStandardPaths::DataLocation, "data/maps/");
//X     }
//X
//X     QString filename;
//X     if (map == "se") {
//X         filename = "se.png";
//X     } else if (map == "uk") {
//X         filename = "uk.png";
//X     } else if (map == "us") {
//X         filename = "us.png";
//X     } else if (map == "ru") {
//X         filename = "ru.png";
//X     } else if (map == "it") {
//X         filename = "it.png";
//X     } else if (map == "de") {
//X         filename = "de.png";
//X     } else if (map == "dk") {
//X         filename = "dk.png";
//X     } else if (map == "fr") {
//X         filename = "fr.png";
//X     } else if (map == "fi") {
//X         filename = "fi.png";
//X     } else if (map == "es") {
//X         filename = "es.png";
//X     } else if (map == "ancient") {
//X         return QBrush(Qt::lightGray);
//X     } else if (map == "uk,fr") {
//X         filename = "ukfr.png";
//X     } else if (map == "se,uk") {
//X         filename = "ukse.png";
//X     } else if (map == "ru,us") {
//X         filename = "ruus.png";
//X     } else {
//X       return QBrush(Qt::blue);
//X     }
//X
//X     QBrush ret;
//X     if (!filename.isEmpty()) {
//X         QPixmap pixmap(resourcepath + filename);
//X         ret = QBrush(pixmap.scaled(elrect.size(), Qt::KeepAspectRatio));
//X     } else {
//X         ret.setColor(Qt::gray);
//X     }
//X
//X     return ret;
//X }
//X
//X QColor KalziumDiscoverymapSchemeType::textColor(int) const
//X {
//X     return Qt::black;
//X }
//X
//X QList<legendPair> KalziumDiscoverymapSchemeType::legendItems() const
//X {
//X     static QString resourcepath;
//X     if (resourcepath.isEmpty()) {
//X         resourcepath = QStandardPaths::locate(QStandardPaths::DataLocation, "data/maps/");
//X     }
//X
//X     QList<legendPair> ll;
//X     ll << qMakePair(i18n("Germany"), QColor(QPixmap(resourcepath + "de.png")));
//X     ll << qMakePair(i18n("United Kindom"), QColor(QPixmap(resourcepath + "uk.png")));
//X     ll << qMakePair(i18n("Sweden"), QColor(QPixmap(resourcepath + "se.png")));
//X     ll << qMakePair(i18n("USA"), QColor(QPixmap(resourcepath + "us.png")));
//X     ll << qMakePair(i18n("Russia"), QColor(QPixmap(resourcepath + "ru.png")));
//X     ll << qMakePair(i18n("Italy"), QColor(QPixmap(resourcepath + "it.png")));
//X     ll << qMakePair(i18n("Denmark"), QColor(QPixmap(resourcepath + "dk.png")));
//X     ll << qMakePair(i18n("France"), QColor(QPixmap(resourcepath + "fr.png")));
//X     ll << qMakePair(i18n("Finland"), QColor(QPixmap(resourcepath + "fi.png")));
//X     ll << qMakePair(i18n("Spain"), QColor(QPixmap(resourcepath + "es.png")));
//X
//X     return ll;
//X }
