//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#

#include <QSet>
#include <QObject>

#ifndef USER_H
#define USER_H

namespace CRAWL {

/**
 * @brief The User class This is internal class for collection all user data and user state.
 */
class User : public QObject
{

    Q_OBJECT

    /**
     * @brief money This current user money count. An user can buy and sell game items using own money amount.
     * @see User::setMoney
     * @see User::getMoney
     */
    Q_PROPERTY(int money READ getMoney WRITE setMoney NOTIFY moneyChanged)

    /**
     * @brief xp This is experience count of an user. The experience unlock new tiers and make available new items for buying.
     * @see User::setXp
     * @see User::getXp
     * @see User::tier
     * @see User::getTier
     */
    Q_PROPERTY(int xp READ getXp WRITE setXp NOTIFY xpChanged)

    /**
     * @brief tier This us user tier. This value automaticaly generated by cuuren user experience count.
     * @see User::xp
     * @see User::getXp
     * @see User::getTier
     */
    Q_PROPERTY(int tier READ getTier NOTIFY tierChanged)

public:
    User();

    /**
     * @brief getMoney This current user money count. An user can buy and sell game items using own money amount.
     * @return current value of the User::money property
     * @see User::setMoney
     * @see User::money
     */
    int getMoney() const;

    /**
     * @brief setMoney This method sets new value of the user money amount.
     * @param newMoney this is new value of users money.
     * @see User::getMoney
     * @see User::money
     */
    void setMoney(int newMoney);

    /**
     * @brief getXp This is experience count of an user. The experience unlock new tiers and make available new items for buying.
     * @return current user xpereans.
     * @see User::setXp
     * @see User::getXp
     * @see User::tier
     * @see User::getTier
     */
    int getXp() const;

    /**
     * @brief setXp This method sets new value of the user experience.
     * @param newXp This is new value of the users experience.
     * @note This method can be change the User::tier property
     * @see User::xp
     * @see User::getXp
     * @see User::tier
     * @see User::getTier
     */
    void setXp(int newXp);

    /**
     * @brief getTier This us user tier. This value automaticaly generated by cuuren user experience count.
     * @return current value of the users tier.
     * @see User::xp
     * @see User::getXp
     * @see User::tier
     */
    int getTier();

    /**
     * @brief unlockedItems This method return set of the unlocked items of this user.
     * @return Set of the unlocked items of this user.
     * @see User::unclokItem
     * @see User::unlockedItems
     * @see User::droppItem
     * @see User::isUnlocked
     * @see User::setUnlockedItems
     */
    const QSet<int> &unlockedItems() const;

    /**
     * @brief isUnlocked This method check if the @a item is unlocked for this user.
     * @param item This is id of the checked item.
     * @return true if the item is uncloked else false.
     * @see User::unclokItem
     * @see User::unlockedItems
     * @see User::droppItem
     * @see User::isUnlocked
     * @see User::setUnlockedItems
     */
    bool isUnlocked(int item) const;

    /**
     * @brief unclokItem This method unclok the @a item for current user.
     * @param item This is id of item that need to unclok.
     * @see User::unclokItem
     * @see User::unlockedItems
     * @see User::droppItem
     * @see User::isUnlocked
     * @see User::setUnlockedItems
     */
    void unclokItem(int item);

    /**
     * @brief droppItem This method dropp item from user.
     * @param item This is id of the dropped item
     * @see User::unclokItem
     * @see User::unlockedItems
     * @see User::droppItem
     * @see User::isUnlocked
     * @see User::setUnlockedItems
     */
    void droppItem(int item);

signals:
    void moneyChanged();
    void tierChanged();
    void xpChanged();

    /**
     * @brief sigUlockedItemsChanged This signal emited when users list of unclode items is changed..
     * @param unclokedItems This is unlocked items set. Each items in the set is id of the unclocked item.
     */
    void sigUlockedItemsChanged(const QSet<int> & unclokedItems);

    /**
     * @brief sigUnlcoked This signal emmited when user unlock one item.
     * @param item This is unlocked item id.
     * @see User::unclokItem
     */
    void sigUnlcoked(int item);

    /**
     * @brief sigDropped This signal emmited when user dropped one item.
     * @param item This is dpopped item id.
     * @see User::droppItem
     */
    void sigDropped(int item);

protected:
    /**
     * @brief setUnlockedItems This method sets new set of uncloked items
     * @param newUnlockedItems This is new set of the uncloked items
     * @see User::unclokItem
     * @see User::unlockedItems
     * @see User::droppItem
     * @see User::isUnlocked
     * @see User::setUnlockedItems
     */
    void setUnlockedItems(const QSet<int> &newUnlockedItems);

private:

    int recalcTier();

    void setTier(int tier);

    int _money = 0;
    int _xp = 0;
    int _tier = 0;
    QSet<int> _unlockedItems;
};
}

#endif // USER_H
