import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/** Fuente, operaciones intermedias y una terminal; Optional; streams de primitivos. */
public class StreamDemo {

    public static void main(String[] args) {
        List<Song> songs = Songs.sample();

        List<String> longTitles = songs.stream()       // fuente
                .filter(s -> s.seconds() > 200)       // intermedia
                .map(Song::title)                      // intermedia
                .sorted()                              // intermedia
                .toList();                             // terminal
        IO.println("largas: " + longTitles);

        long dunas = songs.stream().filter(s -> s.artist().equals("Duna")).count();
        int total = songs.stream().mapToInt(Song::seconds).sum();
        double average = songs.stream().mapToInt(Song::seconds).average().orElse(0);
        IO.println("Duna: " + dunas + ", total: " + total + " s, promedio: " + average + " s");

        boolean anyShort = songs.stream().anyMatch(s -> s.seconds() < 180);
        List<String> artists = songs.stream().map(Song::artist).distinct().sorted().toList();
        IO.println("¿alguna de menos de 3 min? " + anyShort + "; artistas: " + artists);

        Optional<Song> longest = songs.stream().max((a, b) -> Integer.compare(a.seconds(), b.seconds()));
        IO.println("la más larga: " + longest.map(Song::title).orElse("(ninguna)"));
        Optional<Song> none = songs.stream().filter(s -> s.seconds() > 600).findFirst();
        IO.println("¿más de 10 min? " + none.isPresent() + " -> " + none.map(Song::title).orElse("(ninguna)"));

        int sumOfSquares = IntStream.rangeClosed(1, 4).map(n -> n * n).sum();
        Integer reduced = Stream.of(185, 210, 190).reduce(0, Integer::sum);
        IO.println("cuadrados de 1 a 4, sumados = " + sumOfSquares + "; reduce = " + reduced);

        // Un stream se recorre una sola vez.
        Stream<Song> once = songs.stream();
        IO.println("primera vez: " + once.count());
        try {
            IO.println("segunda vez: " + once.count());
        } catch (IllegalStateException e) {
            IO.println(e);
        }
    }
}
