package com.allendowney.thinkdast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


/**
 * Reprezentuje kartę do gry.
 *
 */
public class Card implements Comparable<Card> {

   // reprezentacje figur w postaci łańcuchów znakowych
    public static final String[] RANKS = {
        null, "as", "2", "3", "4", "5", "6", "7",
        "8", "9", "10", "walet", "dama", "król"};

    // reprezentacje kolorów w postaci łańcuchów znakowych
    public static final String[] SUITS = {
        "trefl", "karo", "kier", "pik"};

    // figura i kolor są zmiennymi instancji
    private final int rank;
    private final int suit;

    /**
     * Konstruuje kartę na podstawie podanej figury i koloru
     */
    public Card(int rank, int suit) {
        this.rank = rank;
        this.suit = suit;
    }

    /**
     * Pobiera figurę karty.
     */
    public int getRank() {
        return this.rank;
    }

    /**
     * Pobiera kolor karty.
     */
    public int getSuit() {
        return this.suit;
    }

    /**
     * Zwraca reprezentację karty w postaci łańcucha znakowego.
     */
    public String toString() {
        return RANKS[this.rank] + " - " + SUITS[this.suit];
    }

    /**
     * Zwraca ujemną wartość całkowitą, jeśli bieżąca karta jest słabsza
     * niż podana; zero, jeśli karty te są takie same; dodatnią wartość
     * całkowitą, jeśli bieżąca karta jest silniejsza niż podana.
     */
    public int compareTo(Card that) {
        if (this.suit < that.suit) {
            return -1;
        }
        if (this.suit > that.suit) {
            return 1;
        }
        if (this.rank < that.rank) {
            return -1;
        }
        if (this.rank > that.rank) {
            return 1;
        }
        return 0;
    }

    /**
     * Zwraca wartość true, jeśli podana karta ma tę samą
     * figurę I kolor; w przeciwnym razie zwraca wartość false.
     */
    public boolean equals(Card that) {
        return this.rank == that.rank
            && this.suit == that.suit;
    }

    /**
     * Tworzy kolekcję List zawierającą 52 karty.
     */
    public static List<Card> makeDeck() {
        List<Card> cards = new ArrayList<Card>();
        for (int suit = 0; suit <= 3; suit++) {
            for (int rank = 1; rank <= 13; rank++) {
                Card card = new Card(rank, suit);
                cards.add(card);
            }
        }
        return cards;
    }

    /**
     * Prezentuje sposób wywoływania metod wyszukiwania.
     */
    public static void main(String[] args) {

      // posortuj karty w kolejności naturalnej
        List<Card> cards = makeDeck();
        Collections.sort(cards);
        System.out.println(cards.get(0));
        System.out.println(cards.get(51));

        Comparator<Card> comparator = new Comparator<Card>() {
            @Override
            public int compare(Card card1, Card card2) {
               if (card1.getSuit() < card2.getSuit()) {
                    return -1;
                }
                if (card1.getSuit() > card2.getSuit()) {
                    return 1;
                }
                int rank1 = getRankAceHigh(card1);
                int rank2 = getRankAceHigh(card2);

                if (rank1 < rank2) {
                    return -1;
                }
                if (rank1 > rank2) {
                    return 1;
                }
                return 0;
            }

         private int getRankAceHigh(Card card) {
            int rank = card.getRank();
            if (rank == 1) {
               return 14;
            } else {
               return rank;
            }
         }
        };

        // posortuj karty, używając zewnętrznego komparatora
      Collections.sort(cards, comparator);
        System.out.println(cards.get(0));
        System.out.println(cards.get(51));
    }
}