package pp.battleship.client.gui;

import static pp.util.PreferencesUtils.getPreferences;

import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.prefs.Preferences;

import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetLoadException;
import com.jme3.asset.AssetNotFoundException;
import com.jme3.audio.AudioData;
import com.jme3.audio.AudioNode;

/**
 * Handles the background music beeing played. Is able to start and stop the music. Set the Volume of the Audio.
 */
public class GameMusic extends AbstractAppState{
    private static final Logger LOGGER = System.getLogger(GameMusic.class.getName());
    private static final Preferences PREFERENCES = getPreferences(GameMusic.class);
    private static final String ENABLED_PREF = "enabled"; //NON-NLS
    private static final String VOLUME_PREF = "volume"; //NON-NLS

    private AudioNode music;

    /**
     * Checks if sound is enabled in the preferences.
     *
     * @return {@code true} if sound is enabled, {@code false} otherwise.
     */
    public static boolean enabledInPreferences() {
        return PREFERENCES.getBoolean(ENABLED_PREF, true);
    }

        /**
     * Checks if sound is enabled in the preferences.
     *
     * @return float to which the volume is set
     */
    public static float volumeInPreferences() {
        return PREFERENCES.getFloat(VOLUME_PREF, 0.5f);
    }

    /**
     * Initializes the sound effects for the game.
     * Overrides {@link AbstractAppState#initialize(AppStateManager, Application)}
     *
     * @param stateManager The state manager
     * @param app          The application
     */
    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        super.initialize(stateManager, app);
        music = loadSound(app, "Sound/background.ogg");
        setVolume(volumeInPreferences());
        music.setLooping(true);
        if (isEnabled() && music != null) {
            music.play();
        }
    }

    /**
     * Loads a sound from the specified file.
     *
     * @param app  The application
     * @param name The name of the sound file.
     * @return The loaded AudioNode.
     */
    private AudioNode loadSound(Application app, String name) {
        try {
            final AudioNode sound = new AudioNode(app.getAssetManager(), name, AudioData.DataType.Buffer);
            sound.setLooping(false);
            sound.setPositional(false);
            return sound;
        }
        catch (AssetLoadException | AssetNotFoundException ex) {
            LOGGER.log(Level.ERROR, ex.getMessage(), ex);
        }
        return null;
    }

    /**
     * Sets the enabled state of this AppState.
     * Overrides {@link com.jme3.app.state.AbstractAppState#setEnabled(boolean)}
     *
     * @param enabled {@code true} to enable the AppState, {@code false} to disable it.
     */
    @Override
    public void setEnabled(boolean enabled) {
        if (isEnabled() == enabled) return;

        if (music != null) {
            if (enabled) {
                music.play();
            } else {
                music.stop();
            }
        }
    
        super.setEnabled(enabled);
        LOGGER.log(Level.INFO, "Sound enabled: {0}", enabled); //NON-NLS
        PREFERENCES.putBoolean(ENABLED_PREF, enabled);
    }

    /**
     * Toggles the game sound on or off.
     */
    public void toggleSound() {
        setEnabled(!isEnabled());
    }

    /**
     * Sets the volume of music
     * @param vol the volume to which the music should be set
     */
    public void setVolume(float vol){
        music.setVolume(vol);
        PREFERENCES.putFloat(VOLUME_PREF, vol);
    }
}
