/*
 *  Copyright (C) 2010 Parker Coates <coates@kde.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, see <http://www.gnu.org/licenses/>.
 *
 */

#include "kcarddeck.h"

// own
#include "kcard.h"

class KStandardCardDeckPrivate
{
};

QList<KCardDeck::Suit> KCardDeck::standardSuits()
{
    return QList<Suit>() << Clubs << Diamonds << Hearts << Spades;
}

QList<KCardDeck::Rank> KCardDeck::standardRanks()
{
    return QList<Rank>() << Ace << Two << Three << Four << Five << Six << Seven << Eight << Nine << Ten << Jack << Queen << King;
}

quint32 KCardDeck::getId(KCardDeck::Suit suit, KCardDeck::Rank rank, int number)
{
    return (number << 16) | ((suit & 0xff) << 8) | (rank & 0xff);
}

QList<quint32> KCardDeck::generateIdList(int copies, const QList<Suit> &suits, const QList<Rank> &ranks)
{
    Q_ASSERT(copies >= 1);
    Q_ASSERT(!suits.isEmpty());
    Q_ASSERT(!ranks.isEmpty());

    // Note that changing the order in which the cards are created should be
    // avoided if at all possible. Doing so may effect the game logic of
    // games relying on LibKCardGame.
    QList<quint32> ids;
    unsigned int number = 0;
    for (int c = 0; c < copies; ++c)
        for (const Suit &s : suits)
            for (const Rank &r : ranks)
                ids << getId(s, r, number++);

    return ids;
}

KCardDeck::KCardDeck(const KCardTheme &theme, QObject *parent)
    : KAbstractCardDeck(theme, parent)
    , d(new KStandardCardDeckPrivate)
{
}

KCardDeck::~KCardDeck()
{
    delete d;
}

int KCardDeck::rankFromId(quint32 id) const
{
    int rank = id & 0xff;
    Q_ASSERT(Ace <= rank && rank <= King);
    return rank;
}

int KCardDeck::suitFromId(quint32 id) const
{
    int suit = (id >> 8) & 0xff;
    Q_ASSERT(Clubs <= suit && suit <= Spades);
    return suit;
}

int KCardDeck::colorFromId(quint32 id) const
{
    int suit = suitFromId(id);
    return (suit == Clubs || suit == Spades) ? Black : Red;
}

QString KCardDeck::elementName(quint32 id, bool faceUp) const
{
    if (!faceUp)
        return QStringLiteral("back");

    QString element;

    int rank = rankFromId(id);
    switch (rank) {
    case King:
        element = QStringLiteral("king");
        break;
    case Queen:
        element = QStringLiteral("queen");
        break;
    case Jack:
        element = QStringLiteral("jack");
        break;
    default:
        element = QString::number(rank);
        break;
    }

    switch (suitFromId(id)) {
    case Clubs:
        element += QLatin1String("_club");
        break;
    case Spades:
        element += QLatin1String("_spade");
        break;
    case Diamonds:
        element += QLatin1String("_diamond");
        break;
    case Hearts:
        element += QLatin1String("_heart");
        break;
    }

    return element;
}
