package de.duehl.mp3.unused;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

import java.io.InputStream;
import java.lang.reflect.Field;

import java.util.Scanner;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.SourceDataLine;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.AudioDevice;
import javazoom.jl.player.FactoryRegistry;
import javazoom.jl.player.JavaSoundAudioDevice;
import javazoom.jl.player.advanced.*;
import javazoom.jl.player.advanced.PlaybackListener;

/*
 * Quelle: https://github.com/Gikkman/JavaZoom-Volume-Controll/blob/master/src/main/java/com/gikk/javazoom/JLayerTest.java
 */

public class JLayerTest {
    public static void main(String[] args) {
        String filename = "c:\\Users\\usr207\\Daten\\sprachen\\japanisch\\tmp\\"
                + "Oshi no Ko - Ending 2 - Burning von Hitsujibungaku.mp3";
        SoundJLayer soundToPlay = new SoundJLayer(filename);
        soundToPlay.play();
        System.out.println("HUHU");
        soundToPlay.setVolume(-50f); // tut nichts ... man muss in die Console eingeben!
    }
}

class SoundJLayer extends PlaybackListener implements Runnable {
    private final String filename;
    private AdvancedPlayer player;
    private Thread playerThread;
    private AudioDevice device;
    private FloatControl volControl;

    public SoundJLayer(String filename) {
        this.filename = filename;
    }

    public void play() {
        System.out.println("play()");
        try {
            InputStream stream = createInputStream(filename);

            // InputStream stream = new URL(url).openStream();

            //JavaSoundAudioDevice a = new JavaSoundAudioDevice();

            this.device = FactoryRegistry.systemRegistry().createAudioDevice();
            this.player = new AdvancedPlayer(stream, device);

            this.player.setPlayBackListener(this);
            this.playerThread = new Thread(this, "AudioPlayerThread");
            this.playerThread.start();
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }

        String line = "";
        try (Scanner scanner = new Scanner(System.in)) {
            while (!line.equals("q")) {
                line = scanner.nextLine();

                if (line.matches("^(-?)(0|([1-9][0-9]*))(\\.[0-9]+)?$")) {
                    setVolume(Float.valueOf(line));
                }
            }
            this.player.stop();
        }
    }

    private InputStream createInputStream(String filename) throws IOException {
        return new BufferedInputStream(new FileInputStream(filename));
    }

    // PlaybackListener members
    @Override
    public void playbackStarted(PlaybackEvent playbackEvent) {
        System.out.println("playbackStarted()");
    }

    @Override
    public void playbackFinished(PlaybackEvent playbackEvent) {
        System.out.println("playbackEnded()");
    }

    public void setVolume(float gain) {
        System.out.println("setVolume() gain = " + gain);
        if (this.volControl == null) {
            System.out.println("War null");
            Class<JavaSoundAudioDevice> clazz = JavaSoundAudioDevice.class;
            Field[] fields = clazz.getDeclaredFields();
            try {
                SourceDataLine source = null;
                for (Field field : fields) {
                    if ("source".equals(field.getName())) {
                        field.setAccessible(true);
                        source = (SourceDataLine) field.get(this.device);
                        field.setAccessible(false);
                        this.volControl = (FloatControl) source
                                .getControl(FloatControl.Type.MASTER_GAIN);
                    }
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }

        if (this.volControl == null) {
            System.out.println("Ist immer noch null");
        }
        else {
            float newGain = Math.min(Math.max(gain, volControl.getMinimum()),
                    volControl.getMaximum());
            System.out.println("Was: " + volControl.getValue() + " Will be: " + newGain);

            volControl.setValue(newGain);
        }
    }

    // Runnable members
    @Override
    public void run() {
        try {
            this.player.play();
        }
        catch (JavaLayerException ex) {
            ex.printStackTrace();
        }
    }
}