package com.salcedo.rapbot.object;

import akka.actor.ActorSystem;
import org.opencv.core.Core;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;

import javax.swing.*;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import static java.util.Spliterator.ORDERED;
import static java.util.Spliterators.spliteratorUnknownSize;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.StreamSupport.stream;
import static javax.swing.SwingUtilities.invokeLater;
import static javax.swing.UIManager.setLookAndFeel;

public final class ObjectDetectorTest {
    private static final String APP_NAME = "FaceDetect";
    private final AtomicBoolean isPlayingMusic;
    private final ObjectDetector objectDetector;
    private final JFrame frame;
    private final EmbeddedMediaPlayerComponent playerComponent;
    private final Path musicLibrary;

    private ObjectDetectorTest(final Path musicLibrary) {
        this.musicLibrary = musicLibrary;
        this.isPlayingMusic = new AtomicBoolean(false);
        this.playerComponent = new EmbeddedMediaPlayerComponent();
        this.objectDetector = ObjectDetectors.openCV(ActorSystem.create(APP_NAME));
        this.frame = new JFrame(APP_NAME);
    }

    public static void main(final String[] args) throws Exception {
        setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        final Path musicLibrary = Paths.get("/usr", "src", "app", "Music");
        final ObjectDetectorTest objectDetectorTest = new ObjectDetectorTest(musicLibrary);
        invokeLater(objectDetectorTest::run);
    }

    private void run() {
        System.out.println("\nRunning Face Detect Demo");

        initializeFrame();

        detectLoop();
    }

    private void detectLoop() {
        while (true) {
            try {
                detectFaceAndPlayMusic();
            } catch (final Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void detectFaceAndPlayMusic() {
        if (this.isPlayingMusic.get()) {
            sleep();
        } else {
            if (this.objectDetector.objectDetected()) {
                System.out.println("Face detected.");
                playMusic();
            } else {
                System.out.println("No face detected.");
            }
        }
    }

    private void sleep() {
        try {
            Thread.sleep(TimeUnit.SECONDS.toMillis(5L));
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void initializeFrame() {
        this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.frame.setBounds(100, 100, 640, 480);
        this.frame.setVisible(true);
        this.frame.setContentPane(this.playerComponent);
    }

    private void playMusic() {
        this.playerComponent.getMediaPlayer().playMedia(getSong().toString());
        this.isPlayingMusic.set(true);
    }

    private Path getSong() {
        final Spliterator<Path> spliterator = spliteratorUnknownSize(this.musicLibrary.iterator(), ORDERED);
        final List<String> paths = stream(spliterator, false)
                .distinct()
                .map(Path::toFile)
                .map(File::getName)
                .filter(name -> name.endsWith(".mp3") || name.endsWith(".mp4"))
                .collect(toCollection(ArrayList::new));

        Collections.shuffle(paths);

        if (paths.isEmpty()) {
            throw new IllegalStateException("No songs in music library path: ." + this.musicLibrary);
        }

        return this.musicLibrary.resolve(paths.iterator().next());
    }
}

@@ -199,16 +199,109 @@
 o.File;%0A
+import java.io.IOException;%0Aimport java.io.UncheckedIOException;%0Aimport java.nio.file.Files;%0A
 import j
@@ -432,38 +432,8 @@
 st;%0A
-import java.util.Spliterator;%0A
 impo
@@ -516,31 +516,23 @@
 oolean;%0A
-%0A
 import 
-static 
 java.uti
@@ -537,89 +537,23 @@
 til.
-Spliterator.ORDERED;%0Aimport static java.util.Spliterators.spliteratorUnknownSize;
+stream.Stream;%0A
 %0Aimp
@@ -609,61 +609,8 @@
 on;%0A
-import static java.util.stream.StreamSupport.stream;%0A
 impo
@@ -3203,163 +3203,42 @@
 nal 
-Spliterator%3CPath%3E spliterator = spliteratorUnknownSize(this.musicLibrary.iterator(), ORDERED);%0A        final List%3CString%3E paths = stream(spliterator, false
+List%3CString%3E names = getSongPaths(
 )%0A  
@@ -3499,20 +3499,20 @@
 shuffle(
-path
+name
 s);%0A%0A   
@@ -3520,20 +3520,20 @@
     if (
-path
+name
 s.isEmpt
@@ -3616,17 +3616,16 @@
 y path: 
-.
 %22 + this
@@ -3692,20 +3692,20 @@
 resolve(
-path
+name
 s.iterat
@@ -3723,11 +3723,221 @@
 );%0A    %7D
+%0A%0A    private Stream%3CPath%3E getSongPaths() %7B%0A        try %7B%0A            return Files.list(this.musicLibrary);%0A        %7D catch (final IOException e) %7B%0A            throw new UncheckedIOException(e);%0A        %7D%0A    %7D
 %0A%7D%0A

Fix music library song finding.