import java.util.ArrayList;

/**
 * User & Store Logik
 */
public class User implements Store{
    private String name, nachname, email;
    private Stack stack;
    private DBConnection db;
    private Credentials credentials;
    private Coins coins;

    /**
     * Erstellt einen neuen User
     * @param credentials Zugangsdaten des Users
     * @param name Name des Users
     * @param nachname Nachname des Users
     * @param email Email des Users
     * @param stack Alle Karten des Users
     * @param coins Alle Münzen des Users
     */
    public User(Credentials credentials, String name, String nachname, String email, Stack stack, Coins coins) {
        this.credentials = credentials;
        this.name = name;
        this.nachname = nachname;
        this.email = email;
        this.stack = stack;
        this.coins = coins;
        this.db = new DBConnection();
    }

    /**
     * Holt den Stack des Users
     * @return Stack des Users
     */
    public Stack getStack() {
        return stack;
    }

    /**
     * Setzt den Stack eines Users
     * @param stack Der neue Stack des Users
     */
    public void setStack(Stack stack) {
        this.stack = stack;
    }

    /**
     * Holt das DB Obj
     * @return Das DB Obj
     */
    public DBConnection getDb() {
        return db;
    }

    /**
     * Setzt ein neues DB Obj
     * @param db Das neue DB Obj
     */
    public void setDb(DBConnection db) {
        this.db = db;
    }

    /**
     * Holt die eindeutigen Logindaten des Users
     * @return Eindeutige Logindaten
     */
    public Credentials getCredentials() {
        return credentials;
    }

    /**
     * Setzt die eindeutigen Logindaten
     * @param credentials Die neuen Credentials des Users
     */
    public void setCredentials(Credentials credentials) {
        this.credentials = credentials;
    }

    /**
     * Holt alle Coins des Users
     * @return Coins des Users
     */
    public Coins getCoins() {
        return coins;
    }

    /**
     * Setzt alle Coins des Users
     * @param coins Neue Coins des Users
     */
    public void setCoins(Coins coins) {
        this.coins = coins;
    }

    /**
     * Get Name of User
     * @return Name of User
     */
    public String getName() {
        return this.name;
    }

    /**
     * Get Nachname of User
     * @return Nachname of User
     */
    public String getNachname() {
        return this.nachname;
    }

    /**
     * Email of User
     * @return Email of User
     */
    public String getEmail() {
        return this.email;
    }

    /**
     * Setzt den Namen des Users
     * @param name Neuer Name des Users
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Setzt den Nachnamen
     * @param nachname Neuer Nachname
     */
    public void setNachname(String nachname) {
        this.nachname = nachname;
    }

    /**
     * Setzt die Email des Users
     * @param email Neue Email des Users
     */
    public void setEmail(String email) {
        this.email = email;
    }

    //Store Methoden

    /**
     * Kauft ein Package
     * @param mypackage Package welches gekauft werden soll
     * @return Alle Karten des neuen Package
     * @throws NegativAmountException Wenn ein negativer Preis im Package gesetzt wird.
     */
    public ArrayList<Card> buyPackage(Package mypackage) throws NegativAmountException {
        ArrayList<Package> availablePackages = db.getAllPackages();
        availablePackages.removeIf(obj -> obj.equals(mypackage));
        this.coins.removeCoin(mypackage.getPrice());
        return mypackage.getCards();
    }

    /**
     * Fügt dem Store einen neuen Tradingdeal hinzu
     * @param tradingDeal Der neue Tradingdeal
     */
    public void addTradingDeal(TradingDeal tradingDeal) {
        db.addTradingDeal(tradingDeal);
    }

    /**
     * Holt alle verfügbaren Tradingdeals
     * @return Alle verfügbaren Deals
     */
    public ArrayList<TradingDeal> getTradingDeals() {
        return db.getAllTradingDeals();
    }

    /**
     * Startet ein Trading zw 2 TradingDeals
     * @param myTradingDeal Wenn der Deal passt, wird diese Karte aus dem Stack entfernt
     * @param storeTradingDeal Wenn der Deal passt, wird diese Karte dem Stack hinzugefügt
     * @return True wenn erfolgreich, False wenn die Deals nicht zusammenpassen
     */
    public boolean doTrading(TradingDeal myTradingDeal, TradingDeal storeTradingDeal) {
        if (storeTradingDeal.dealOk(myTradingDeal)){
            stack.delCard(myTradingDeal.getCardToTrade());
            stack.addCard(storeTradingDeal.getCardToTrade());
        }
        return false;
    }

    /**
     * Gibt alle Möglichen Trading Deals zurück
     * @param toTrade Prüft nach diesem Deal
     * @return
     */
    @Override
    public ArrayList<TradingDeal> getPossibleTradingDeals(Card toTrade) {
        ArrayList<TradingDeal> storeList = db.getAllTradingDeals();
        ArrayList<TradingDeal> possible = new ArrayList<TradingDeal>();
        storeList.forEach(item -> {
            if(item.cardOk(toTrade)){
                possible.add(item);
            }
        });
        return possible;
    }

    /**
     * Checkt ob es sich um den selben User handelt
     * @param toCheck Mit diesem User wird verglichen
     * @return True wenn es der selbe User ist
     */
    public boolean equals(User toCheck){
        if (toCheck.getCredentials().getUsername() == this.credentials.getUsername() && toCheck.getCredentials().getPasswort() == this.credentials.getPasswort()){
            return true;
        }else {
            return false;
        }
    }
}