import java.util.Comparator;
import java.util.List;

/** El mismo comparador escrito de cuatro maneras: clase, clase anónima, lambda y referencia a método. */
public class ThreeWaysDemo {

    static String titles(List<Song> songs) {
        StringBuilder sb = new StringBuilder();
        for (Song s : songs) {
            sb.append(s.title()).append(s.seconds() == 190 ? "*" : "").append("  ");
        }
        return sb.toString().strip();
    }

    public static void main(String[] args) {
        // 1. Una clase con nombre, en su propio archivo (semana 11).
        Comparator<Song> byClass = new ByDuration();

        // 2. Una clase anónima: se declara y se instancia en el mismo lugar.
        Comparator<Song> byAnonymous = new Comparator<Song>() {
            @Override
            public int compare(Song a, Song b) {
                return Integer.compare(a.seconds(), b.seconds());
            }
        };

        // 3. Una lambda: solo los parámetros y el cuerpo del único método abstracto.
        Comparator<Song> byLambda = (a, b) -> Integer.compare(a.seconds(), b.seconds());

        // 4. Un static factory method que recibe la función que extrae la clave.
        Comparator<Song> byKey = Comparator.comparingInt(Song::seconds);

        List<Comparator<Song>> all = List.of(byClass, byAnonymous, byLambda, byKey);
        String[] names = {"clase", "anónima", "lambda", "comparingInt"};
        for (int i = 0; i < all.size(); i++) {
            List<Song> songs = Songs.sample();
            songs.sort(all.get(i));
            IO.println(String.format("%-13s %s", names[i] + ":", titles(songs)));
        }

        // Comparadores compuestos: por artista, luego de la más larga a la más corta.
        List<Song> songs = Songs.sample();
        songs.sort(Comparator.comparing(Song::artist)
                .thenComparing(Song::seconds, Comparator.reverseOrder()));
        IO.println("artista, luego duración descendente:");
        songs.forEach(s -> IO.println("  " + s.artist() + " - " + s.title() + " (" + s.seconds() + ")"));

        songs.sort(Comparator.comparing(Song::title).reversed());
        IO.println("título, al revés: " + titles(songs));
    }
}
