/*******************************************************************************
 * Copyright (c) 2003, 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - Initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.server.ui.internal.audio;

import java.util.*;
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;

import org.eclipse.core.runtime.*;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
import org.eclipse.wst.server.ui.internal.Trace;
/**
 * Main audio plugin class.
 */
public class AudioCore {
	protected static AudioCore instance;

	public static final String PREF_SOUND_ENABLED = "soundEnabled";
	public static final String PREF_VOLUME = "volume";

	public static final String SOUNDS_FILE = "sounds.xml";
	public static final String DISABLED_FILE = "disabled-sounds.xml";

	// Categories - map of String id to String names
	private Map<String, String> categories;

	// Sounds - map of String id to Sound
	private Map<String, Sound> sounds;

	// specific sounds or categories that have been disabled, by id
	private List<String> disabledSounds;
	private List<String> disabledCategories;

	// SoundMap - map of String id to an IPath
	private Map<String, IPath> userSoundMap;

	/**
	 * AudioCore constructor comment.
	 */
	private AudioCore() {
		super();
	
		loadExtensionPoints();
	
		loadSoundMap();
		loadDisabledLists();
		
		
	}

	/**
	 * Return the categories
	 *
	 * @return java.util.Map
	 */
	protected Map<String, String> getCategories() {
		return categories;
	}

	/**
	 * Returns the audio clip.
	 *
	 * @param url java.net.URL
	 * @return javax.sound.sampled.Clip
	 */
	protected static Clip getClip(URL url) {
		try {
			AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
	
			AudioFormat format = audioInputStream.getFormat();
	
			/**
			 * we can't yet open the device for ALAW/ULAW playback,
			 * convert ALAW/ULAW to PCM
			 */
			if ((format.getEncoding() == AudioFormat.Encoding.ULAW) ||
				(format.getEncoding() == AudioFormat.Encoding.ALAW)) {
				AudioFormat tmp = new AudioFormat(
					AudioFormat.Encoding.PCM_SIGNED, 
					format.getSampleRate(),
					format.getSampleSizeInBits() * 2,
					format.getChannels(),
					format.getFrameSize() * 2,
					format.getFrameRate(), true);
				audioInputStream = AudioSystem.getAudioInputStream(tmp, audioInputStream);
				format = tmp;
			}
			DataLine.Info info = new DataLine.Info(
				Clip.class, audioInputStream.getFormat(), 
				((int) audioInputStream.getFrameLength() *
				format.getFrameSize()));
		
			Clip clip = (Clip) AudioSystem.getLine(info);
			clip.open(audioInputStream);
			return clip;
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Could not get clip: " + url, e);
			}
		}
		return null;
	}
	
	/**
	 * Returns true if audio is currently available on this system.
	 *
	 * @return boolean
	 */
	protected static boolean isAudioSupported() {
		try {
			boolean sound = false;
			Mixer.Info[] info2 = AudioSystem.getMixerInfo();
			if (info2 != null) {
				int size = info2.length;
				for (int i = 0; i < size; i++) {
					//Trace.trace(" " + info2[i]);
					Mixer mixer = AudioSystem.getMixer(info2[i]);
					if (mixer != null) {
						//Trace.trace("   Mixer:" + mixer);
						//Trace.trace("   " + mixer.getLineInfo());
						try {
							Line.Info info = mixer.getLineInfo();
							Line line = mixer.getLine(info);
							//Trace.trace("   Line:" + line);
							if (line != null && line.toString().indexOf("Output") >= 0)
								sound = true;
						} catch (Exception e) {
							// ignore
						}
					}
				}
			}
			return sound;
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Could not verify audio status", e);
			}
		}
		return true;
	}
	
	/**
	 * Returns true if sound is enabled.
	 *
	 * @return boolean
	 */
	public boolean getDefaultSoundsEnabled() {
		return getPreferenceStore().getDefaultBoolean(PREF_SOUND_ENABLED);
	}

	/**
	 * Returns the default volume.
	 *
	 * @return int
	 */
	public int getDefaultVolume() {
		return getPreferenceStore().getDefaultInt(PREF_VOLUME);
	}

	/**
	 * Returns the singleton instance.
	 *
	 * @return org.eclipse.audio.internal.AudioCore
	 */
	public static AudioCore getInstance() {
		if (instance == null)
			instance = new AudioCore();
		return instance;
	}

	/**
	 * 
	 * @return org.eclipse.jface.preference.IPreferenceStore
	 */
	protected IPreferenceStore getPreferenceStore() {
		return ServerUIPlugin.getInstance().getPreferenceStore();
	}

	/**
	 * Returns the sound with the given id.
	 *
	 * @param id java.lang.String
	 * @return org.eclipse.audio.Sound
	 */
	protected Sound getSound(String id) {
		try {
			return sounds.get(id);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * Return the sounds.
	 *
	 * @return java.util.Map
	 */
	protected Map<String, Sound> getSounds() {
		return sounds;
	}

	/**
	 * Returns the full user sound map.
	 *
	 * @return java.util.Map
	 */
	protected Map<String, IPath> getUserSoundMap() {
		if (userSoundMap == null)
			loadSoundMap();
		return userSoundMap;
	}

	/**
	 * Return the current URL for this sound.
	 *
	 * @param id java.lang.String
	 * @return java.net.URL
	 */
	protected IPath getUserSoundPath(String id) {
		try {
			if (userSoundMap == null)
				loadSoundMap();
	
			IPath path = userSoundMap.get(id);
			if (path != null)
				return path;
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Could not get sound URL: " + id, e);
			}
		}
		return null;
	}

	/**
	 * Returns the preferred volume.
	 *
	 * @return int
	 */
	public int getVolume() {
		return getPreferenceStore().getInt(PREF_VOLUME);
	}

	/**
	 * Initialize the default preferences.
	 *
	 * @param store org.eclipse.jface.preference.IPreferenceStore
	 */
	public static void initializeDefaultPreferences(IPreferenceStore store) {
		store.setDefault(PREF_VOLUME, 18);
	}

	/**
	 * Returns true if the given category is enabled.
	 *
	 * @param id java.lang.String
	 * @return boolean
	 */
	public boolean isCategoryEnabled(String id) {
		if (id == null)
			return false;
	
		if (disabledCategories == null)
			loadDisabledLists();
	
		return (!disabledCategories.contains(id));
	}

	/**
	 * Returns true if sound is enabled.
	 *
	 * @return boolean
	 */
	public boolean isSoundEnabled() {
		return getPreferenceStore().getBoolean(PREF_SOUND_ENABLED);
	}

	/**
	 * Returns true if the given sound is enabled.
	 *
	 * @param id java.lang.String
	 * @return boolean
	 */
	public boolean isSoundEnabled(String id) {
		if (id == null)
			return false;
	
		if (disabledSounds == null)
			loadDisabledLists();
	
		return (!disabledSounds.contains(id));
	}

	/**
	 * Saves the disabled sound list.
	 */
	private void loadDisabledLists() {
		String filename = ServerUIPlugin.getInstance().getStateLocation().append(DISABLED_FILE).toOSString();
	
		FileInputStream in = null;
		disabledCategories = new ArrayList<String>();
		disabledSounds = new ArrayList<String>();
		try {
			in = new FileInputStream(filename);
			IMemento memento = XMLMemento.loadMemento(in);
	
			IMemento cat = memento.getChild("categories");
			IMemento[] children = cat.getChildren("category");
	
			int size = children.length;
			for (int i = 0; i < size; i++) {
				try {
					IMemento child = children[i];
					String id = child.getString("id");
	
					disabledCategories.add(id);
				} catch (Exception ex) {
					if (Trace.SEVERE) {
						Trace.trace(Trace.STRING_SEVERE, "Error reading URL map ", ex);
					}
				}
			}
	
			IMemento sound = memento.getChild("sounds");
			children = sound.getChildren("sound");
	
			size = children.length;
			for (int i = 0; i < size; i++) {
				try {
					IMemento child = children[i];
					String id = child.getString("id");
	
					disabledSounds.add(id);
				} catch (Exception ex) {
					if (Trace.SEVERE) {
						Trace.trace(Trace.STRING_SEVERE, "Error reading URL map ", ex);
					}
				}
			}
		} catch (Exception e) {
			//AudioPlugin.log(new Status(IStatus.WARNING, AudioPlugin.PLUGIN_ID, 0, "Could not load disabled sound information", e));
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (Exception e) {
					// ignore
				}
			}
		}
	}

	/**
	 * Load extension point.
	 */
	private void loadExtensionPoints() {
		// load extension points
		IExtensionRegistry registry = Platform.getExtensionRegistry();
		IConfigurationElement[] cf = registry.getConfigurationElementsFor(ServerUIPlugin.PLUGIN_ID, "audio");
	
		int size = cf.length;
		categories = new HashMap<String, String>();
		sounds = new HashMap<String, Sound>();
	
		for (int i = 0; i < size; i++) {
			try {
				String elementName = cf[i].getName();
				String id = cf[i].getAttribute("id");
				String name = cf[i].getAttribute("name");
				if ("category".equals(elementName)) {
					categories.put(id, name);
				} else if ("sound".equals(elementName)) {
					String category = cf[i].getAttribute("category");
					String location = cf[i].getAttribute("location");
	
					URL realURL = null;
					if (location != null && location.length() > 0) {
						String pluginId = cf[i].getDeclaringExtension().getContributor().getName();
						URL url = FileLocator.find(Platform.getBundle(pluginId), new Path(location), null);
						realURL = FileLocator.resolve(url);
					}
	
					Sound sound = new Sound(id, category, name, realURL);
					sounds.put(id, sound);
				}
			} catch (Throwable t) {
				if (Trace.SEVERE) {
					Trace.trace(Trace.STRING_SEVERE, "Could not load audio: " + cf[i].getAttribute("id"), t);
				}
			}
		}
	}

	/**
	 * Saves the disabled sound list.
	 */
	private void loadSoundMap() {
		String filename = ServerUIPlugin.getInstance().getStateLocation().append(SOUNDS_FILE).toOSString();
	
		InputStream in = null;
		userSoundMap = new HashMap<String, IPath>();
		try {
			in = new FileInputStream(filename);
			IMemento memento = XMLMemento.loadMemento(in);
	
			IMemento[] children = memento.getChildren("map");
	
			int size = children.length;
			for (int i = 0; i < size; i++) {
				try {
					IMemento child = children[i];
					String id = child.getString("id");
					String pathStr = child.getString("path");
					IPath path = new Path(pathStr);
	
					userSoundMap.put(id, path);
				} catch (Exception ex) {
					if (Trace.SEVERE) {
						Trace.trace(Trace.STRING_SEVERE, "Error reading URL map ", ex);
					}
				}
			}
		} catch (Exception e) {
			// ignore
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (Exception e) {
					// ignore
				}
			}
		}
	}

	/**
	 * Play the sound with the given id. (provided that
	 * the user has enabled the sound)
	 *
	 * @param id java.lang.String
	 */
	public void playSound(String id) {
		if (!isSoundEnabled())
			return;
	
		if (!isSoundEnabled(id))
			return;
	
		try {
			Sound sound = sounds.get(id);
			String category = sound.getCategory();
			if (category != null && categories.containsKey(category)) {
				if (!isCategoryEnabled(category))
					return;
			}
	
			URL url = sound.getLocation();
			IPath path = getUserSoundPath(id);
			if (path != null)
				url = path.toFile().toURL();
	
			playSound(url, getVolume());
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Error playing audio: " + id, e);
			}
		}
	}

	/**
	 * Plays the sound at the given url.
	 *
	 * @param url java.net.URL
	 */
	protected static void playSound(URL url, final int volume) {
		try {
			if (Trace.FINEST) {
				Trace.trace(Trace.STRING_FINEST, "playSound");
			}
			if (url == null || volume <= 0)
				return;
	
			final Clip clip = getClip(url);
			if (clip == null)
				return;
				
			if (Trace.FINEST) {
				Trace.trace(Trace.STRING_FINEST, "playing");
			}
	
			Thread t = new Thread("Sound Thread") {
				public void run() {
					// set gain
					FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
					double value = volume / 20.0;
					float dB = (float) (Math.log(value==0.0?0.0001:value)/Math.log(10.0)*20.0);
					gainControl.setValue(dB);
	
					if (Trace.FINEST) {
						Trace.trace(Trace.STRING_FINEST, "start");
					}
					clip.start();
					try {
						sleep(99);
					} catch (Exception e) {
						// ignore
					}
	
					while (clip.isActive()) {
						try {
							sleep(99);
						} catch (Exception e) {
							break;
						}
					}
					clip.stop();
					clip.close();
					if (Trace.FINEST) {
						Trace.trace(Trace.STRING_FINEST, "stop");
					}
				}
			};
			t.setDaemon(true);
			t.start();
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Error playing audio: " + url, e);
			}
		}
	}

	/**
	 * Saves the disabled sounds and categories list.
	 */
	private void saveDisabledLists() {
		String filename = ServerUIPlugin.getInstance().getStateLocation().append(DISABLED_FILE).toOSString();
	
		FileOutputStream fout = null;
		try {
			XMLMemento memento = XMLMemento.createWriteRoot("disabled");
	
			IMemento cat = memento.createChild("categories");
			Iterator iterator = disabledCategories.iterator();
			while (iterator.hasNext()) {
				IMemento child = cat.createChild("category");
				String id = (String) iterator.next();
				child.putString("id", id);
			}
	
			IMemento sound = memento.createChild("sounds");
			iterator = disabledSounds.iterator();
			while (iterator.hasNext()) {
				IMemento child = sound.createChild("sound");
				String id = (String) iterator.next();
				child.putString("id", id);
			}
	
			fout = new FileOutputStream(filename);
			memento.save(fout);
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Could not save disabled information", e);
			}
		} finally {
			if (fout != null) {
				try {
					fout.close();
				} catch (Exception e) {
					// ignore
				}
			}
		}
	}

	/**
	 * Saves the disabled sound list.
	 */
	private void saveSoundMap() {
		String filename = ServerUIPlugin.getInstance().getStateLocation().append(SOUNDS_FILE).toOSString();
	
		FileOutputStream fout = null;
		try {
			XMLMemento memento = XMLMemento.createWriteRoot("sound-map");
	
			Iterator iterator = userSoundMap.keySet().iterator();
			while (iterator.hasNext()) {
				IMemento child = memento.createChild("map");
				String id = (String) iterator.next();
				child.putString("id", id);
				IPath path = userSoundMap.get(id);
				child.putString("path", path.toString());
			}
	
			fout = new FileOutputStream(filename);
			memento.save(fout);
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Could not save URL map information", e);
			}
		} finally {
			if (fout != null) {
				try {
					fout.close();
				} catch (Exception e) {
					// ignore
				}
			}
		}
	}

	/**
	 * Enable or disable a specific category.
	 *
	 * @param id java.lang.String
	 * @param b boolean
	 */
	public void setCategoryEnabled(String id, boolean b) {
		if (id == null)
			return;
	
		if (disabledCategories == null)
			loadDisabledLists();
	
		if (b) {
			if (disabledCategories.contains(id)) {
				disabledCategories.remove(id);
				saveDisabledLists();
			}
		} else {
			if (!disabledCategories.contains(id)) {
				disabledCategories.add(id);
				saveDisabledLists();
			}
		}
	}

	/**
	 * Enable or disable a specific sound.
	 *
	 * @param id java.lang.String
	 * @param b boolean
	 */
	public void setSoundEnabled(String id, boolean b) {
		if (id == null)
			return;
	
		if (disabledSounds == null)
			loadDisabledLists();
	
		if (b) {
			if (disabledSounds.contains(id)) {
				disabledSounds.remove(id);
				saveDisabledLists();
			}
		} else {
			if (!disabledSounds.contains(id)) {
				disabledSounds.add(id);
				saveDisabledLists();
			}
		}
	}

	/**
	 * Sets whether sound is enabled.
	 *
	 * @param enabled
	 */
	public void setSoundsEnabled(boolean enabled) {
		getPreferenceStore().setValue(PREF_SOUND_ENABLED, enabled);
	}

	/**
	 * Sets the current URL for this sound.
	 *
	 * @param id java.lang.String
	 * @param path IPath
	 */
	protected void setSoundURL(String id, IPath path) {
		if (id == null || path == null)
			return;
	
		try {
			if (userSoundMap == null)
				loadSoundMap();
	
			userSoundMap.put(id, path);
			saveSoundMap();
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Could not get sound URL: " + id, e);
			}
		}
	}

	/**
	 * Sets the full user sound map.
	 *
	 * @param map the sound map
	 */
	protected void setUserSoundMap(Map<String, IPath> map) {
		if (map != null) {
			userSoundMap = map;
			saveSoundMap();
		}
	}

	/**
	 * Sets the volume.
	 *
	 * @param volume the volume
	 */
	public void setVolume(int volume) {
		getPreferenceStore().setValue(PREF_VOLUME, volume);
	}
}
