package me.hammerle.supersnuvi.util;

import java.io.File;
import java.util.Arrays;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import me.hammerle.supersnuvi.gamelogic.StateRenderer;
import me.hammerle.supersnuvi.javafx.JavaRenderer;

public class SoundUtils 
{
    private static SoundPlayer soundPlayer;
            
    public static void initSounds()
    {
        soundPlayer = new SoundPlayer(!StateRenderer.CONFIG.getBoolean("sound", false));
        //new Thread(soundPlayer).start();
    }
    
    public enum Sound
    {
        COLLECT(true), 
        JUMP(true), 
        JUMP_ON_BOUNCE_SHROOM(false), 
        STONE_CRUMBLING(true), 
        WALK(false), 
        WALK_WATER(false),
        MENU_MUSIC(false), 
        SONG_1(false);
        
        private final boolean reset;
        
        Sound(boolean reset)
        {
            this.reset = reset;
        }
        
        public boolean shouldReset()
        {
            return reset;
        }
    }
    
    private static class SoundPlayer implements Runnable
    {
        private final MediaPlayer collect;
        private final MediaPlayer jump;
        private final MediaPlayer jumpOnBounceShroom;
        private final MediaPlayer stoneCrumbling;
        private final MediaPlayer walk;
        private final MediaPlayer walkWater;

        private final MediaPlayer menuMusic;
        private final MediaPlayer song1;
        
        private final boolean noSound;
        
        private final boolean[] playState;
        private boolean shouldRun;
        
        public SoundPlayer(boolean noSound)
        {
            this.noSound = noSound;
            shouldRun = false;
            
            collect = getMedia("collect");
            jump = getMedia("jump");
            jumpOnBounceShroom = getMedia("jump_on_bounce_shroom");
            stoneCrumbling = getMedia("stone_crumbling");
            walk = getMedia("walk");
            walkWater = getMedia("walk_water");

            menuMusic = getMedia("menu_music", true);
            song1 = getMedia("song1", true);
            
            playState = new boolean[Sound.values().length];
            Arrays.fill(playState, false);
        }
        
        private MediaPlayer getMedia(String path, boolean loop)
        {
            if(noSound)
            {
                return null;
            }
            Media sound = new Media(new File("sounds/" + path + ".wav").toURI().toString());
            MediaPlayer mp = new MediaPlayer(sound);
            mp.setCycleCount(MediaPlayer.INDEFINITE);
            if(loop)
            {
                mp.setCycleCount(MediaPlayer.INDEFINITE);
            }
            else
            {
                mp.setOnEndOfMedia(() -> 
                {
                    mp.stop();
                });
            }
            return mp;
        }
        
        private MediaPlayer getMedia(String path)
        {
            return getMedia(path, false);
        }
        
        public synchronized void playSound(Sound sound)
        {
            if(noSound)
            {
                return;
            }
            shouldRun = true;
            playState[sound.ordinal()] = true;
        }
        
        public synchronized void playSounds()
        {
            if(!noSound && shouldRun)
            {
                this.notifyAll();
            }
        }
        
        public void stopSound(Sound sound)
        {
            if(noSound)
            {
                return;
            }
            getMediaPlayer(sound).stop();
        }
        
        private MediaPlayer getMediaPlayer(Sound sound)
        {
            switch(sound)
            {
                case COLLECT: return collect;
                case JUMP: return jump;
                case JUMP_ON_BOUNCE_SHROOM: return jumpOnBounceShroom;
                case MENU_MUSIC: return menuMusic;
                case SONG_1: return song1;
                case STONE_CRUMBLING: return stoneCrumbling;
                case WALK: return walk;
                case WALK_WATER: return walkWater;
            }
            return null;
        }

        @Override
        public void run() 
        {
            /*while(GameWindow.isRunning)
            {
                final boolean[] states;
                synchronized(this)
                {
                    states = Arrays.copyOf(soundPlayer.playState, soundPlayer.playState.length);
                    Arrays.fill(soundPlayer.playState, false);
                }
                Sound sound;
                MediaPlayer mp;
                for(int i = 0; i < states.length; i++)
                {
                    if(states[i])
                    {
                        states[i] = false;
                        sound = Sound.values()[i];
                        mp = soundPlayer.getMediaPlayer(sound);
                        if(sound.shouldReset())
                        {
                            mp.seek(mp.getStartTime());
                        }
                        mp.play();
                    }
                }
                
                synchronized(this)
                {
                    try
                    {
                        this.wait();
                    }
                    catch(InterruptedException ex)
                    {

                    }
                }
            }*/
        }
    }
    
    public static void playSounds()
    {
        soundPlayer.playSounds();
    }
    
    public static void playSound(Sound sound)
    {
        soundPlayer.playSound(sound);
    }
    
    public static void stopSound(Sound sound)
    {
        soundPlayer.stopSound(sound);
    }
}
