/*******************************************************************************
 * Copyright (c) 2009, 2010 Nokia 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:
 * Nokia - Initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.debug.edc.internal.snapshot;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.PathUtils;
import org.eclipse.cdt.debug.edc.internal.ZipFileUtils;
import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl;
import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
import org.eclipse.cdt.debug.edc.services.Stack;
import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;
import org.eclipse.cdt.debug.edc.snapshot.IAlbum;
import org.eclipse.cdt.debug.internal.core.sourcelookup.MapEntrySourceContainer;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.service.DsfSession.SessionEndedListener;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer;
import org.eclipse.debug.internal.core.LaunchManager;
import org.osgi.framework.Bundle;
import org.osgi.service.prefs.BackingStoreException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * The Album class represents a series of snapshots that record moments in a
 * debug session. An Album manages the collection of snapshots, common resources
 * such as source files, persistence, and association with debug sessions.
 * 
 * An Album is usually created during a debug session, saved at the conclusion
 * of the session, and reopened by a launch delegate for a new snapshot debug
 * session.
 * 
 * When an Album is saved it's data and resources are archived in a snapshot
 * file in a default location. When reopened the contents are expanded into a
 * temporary directory and used to recreate the debug session.
 */
@SuppressWarnings("restriction")
public class Album extends PlatformObject implements IAlbum {

	// XML element names
	public static final String SNAPSHOT = "snapshot";
	private static final String ALBUM = "album";
	private static final String LAUNCH = "launch";
	private static final String RESOURCES = "resources";
	private static final String FILE = "file";
	private static final String INFO = "info";

	public static final String METADATA = "snapshotMetaData";
	public static final String SNAPSHOT_LIST = "snapshots";

	private static final String ALBUM_DATA = "album.xml";
	private static final String ALBUM_VERSION = "100";

	private static String[] DSA_FILE_EXTENSIONS = new String[] {"dsa"};

	// Preferences
	public static final String PREF_CREATION_CONTROL = "creation_control";
	public static final String CREATE_MANUAL = "manual";
	public static final String CREATE_WHEN_STOPPED = "suspend";
	public static final String CREATE_AT_BEAKPOINTS = "breakpoints";	
	
	public static final String PREF_VARIABLE_CAPTURE_DEPTH = "variable_capture_depth";
	public static final String PLAY_SNAPSHOT_DELAY_TIME = "play_snapshot_delay_time";

	private static final String CAMERA_CLICK_WAV = "/sounds/camera_click.wav";
	
	private Document document;
	private Element albumRootElement;

	private final List<Snapshot> snapshotList = new ArrayList<Snapshot>();
	private String sessionID = "";
	private String recordingSessionID = "";
	private IPath albumRootDirectory;
	private boolean launchConfigSaved;
	private String launchType;
	private HashMap<String, Object> launchProperties;
	private String launchName = "";
	private String name;
	private boolean loaded;
	private boolean metaDataLoaded;
	private final Set<IPath> files = new HashSet<IPath>();

	private int currentSnapshotIndex;
	private IPath location;
	private boolean resourceListSaved;
	private boolean metadataSaved;
	private boolean albumInfoSaved;
	private String displayName;
	private boolean playingSnapshots;

	/**
     * Listener for state changes on albums
     */
	protected static List<ISnapshotAlbumEventListener> listeners = Collections.synchronizedList(new ArrayList<ISnapshotAlbumEventListener>());

	private static Map<String, Album> albumsBySessionID = Collections.synchronizedMap(new HashMap<String, Album>());
	private static Map<String, Album> albumsRecordingBySessionID = Collections.synchronizedMap(new HashMap<String, Album>());	
	private static Map<IPath, Album> albumsByLocation = Collections.synchronizedMap(new HashMap<IPath, Album>());
	private static Map<String, Integer> launchNames = Collections.synchronizedMap(new HashMap<String, Integer>());

	private static boolean sessionEndedListenerAdded;
	private static SessionEndedListener sessionEndedListener = new SessionEndedListener() {

		public void sessionEnded(DsfSession session) {
			Album album = albumsRecordingBySessionID.get(session.getId());
			if (album == null)
				album = albumsBySessionID.get(session.getId());
			if (album != null && session.getId().equals(album.getRecordingSessionID())) {
				album.saveResources(new NullProgressMonitor());
				album.setRecordingSessionID("");
			}
			synchronized (albumsRecordingBySessionID) {
			albumsRecordingBySessionID.remove(session.getId());
			}
			synchronized (albumsBySessionID) {
			albumsBySessionID.remove(session.getId());
			}

			if (album != null) {
				for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {
					l.snapshotSessionEnded(album, session);
				}
			}
		}
	};

	public interface IAlbumArchiveEntry {

		public String createEntryName(File file);

	}

	public Album() {
		super();
		try {
			setDocument(DebugPlugin.newDocument());
			if (!sessionEndedListenerAdded)
				DsfSession.addSessionEndedListener(sessionEndedListener);
			sessionEndedListenerAdded = true;
		} catch (CoreException e) {
			EDCDebugger.getMessageLogger().logError(null, e);
		}

	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getName()
	 */
	public String getName() {
		if (name == null) {
			name = getDefaultAlbumName();
		}
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setDisplayName(String displayName) {
		this.displayName = displayName;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getDisplayName()
	 */
	public String getDisplayName() {
		if (displayName == null || displayName.length() == 0) {
			displayName = getName();
		}
		return displayName;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getSessionID()
	 */
	public String getSessionID() {
		sessionID = "";
		if (albumsBySessionID != null) {
			for (Map.Entry<String, Album> entry : albumsBySessionID.entrySet()){
				if (entry.getValue().location != null && entry.getValue().location.equals(getLocation())){
					sessionID = entry.getKey();
				}
			}
		}
		return sessionID;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getRecordingSessionID()
	 */
	public String getRecordingSessionID() {
		return recordingSessionID;
	}

	public void setRecordingSessionID(String sessionID) {
		this.recordingSessionID = sessionID;
		if (sessionID.length() > 0)
			albumsRecordingBySessionID.put(sessionID, this);
	}

	public void setSessionID(String sessionID) {
		this.sessionID = sessionID;
		if (sessionID.length() > 0)
			albumsBySessionID.put(sessionID, this);
	}
	
	/**
	 * Is the album currently open for recording
	 * @param sessionId
	 * @return true if the album is currently being recording by an active debug session
	 */
	public static boolean isSnapshotSession(String sessionId) {
		EDCLaunch launch = EDCLaunch.getLaunchForSession(sessionId);
		return launch != null && launch.isSnapshotLaunch();
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#createSnapshot(org.eclipse.cdt.dsf.service.DsfSession, org.eclipse.cdt.debug.edc.internal.services.dsf.Stack.StackFrameDMC, org.eclipse.core.runtime.IProgressMonitor)
	 */
	public Snapshot createSnapshot(DsfSession session, StackFrameDMC stackFrame, IProgressMonitor monitor) throws Exception {
		SubMonitor progress = SubMonitor.convert(monitor, "Creating Snapshot", 10000);
		configureAlbum();
		progress.worked(100);
		
		if (getLocation() == null || !getLocation().toFile().exists()){
				createEmptyAlbum(); 
		}
		
		Snapshot snapshot = new Snapshot(this, session, stackFrame);
		snapshot.writeSnapshotData(progress.newChild(7900));

		snapshotList.add(snapshot);
		saveAlbum(progress.newChild(1000));
		
		monitor.done();
		return snapshot;
	}

	private void configureAlbum() {
		saveAlbumInfo();
		saveLaunchConfiguration();
	}

	private void saveAlbumInfo() {
		if (!albumInfoSaved) {
			Element infoElement = document.createElement(INFO);
			infoElement.setAttribute("version", ALBUM_VERSION);
			Calendar calendar = Calendar.getInstance();
			infoElement.setAttribute("month", Integer.toString(calendar.get(Calendar.MONTH)));
			infoElement.setAttribute("day", Integer.toString(calendar.get(Calendar.DATE)));
			infoElement.setAttribute("year", Integer.toString(calendar.get(Calendar.YEAR)));
			infoElement.setAttribute("hour", Integer.toString(calendar.get(Calendar.HOUR)));
			infoElement.setAttribute("minute", Integer.toString(calendar.get(Calendar.MINUTE)));
			infoElement.setAttribute("second", Integer.toString(calendar.get(Calendar.SECOND)));

			Properties systemProps = System.getProperties();
			Map<String, Object> infoProps = new HashMap<String, Object>();
			Set<Object> systemKeys = systemProps.keySet();

			for (Object sysKey : systemKeys) {
				if (sysKey instanceof String)
					infoProps.put((String) sysKey, systemProps.get(sysKey));
			}
			Element propsElement = SnapshotUtils.makeXMLFromProperties(document, infoProps);
			infoElement.appendChild(propsElement);

			getAlbumRootElement().appendChild(infoElement);
			albumInfoSaved = true;
		}
	}

	private void saveResourceList() {
		if (!resourceListSaved) {
			Element resourcesElement = document.createElement(RESOURCES);
			for (IPath filePath : files) {
				Element fileElement = document.createElement(FILE);
				fileElement.setAttribute("path", filePath.toOSString());
				resourcesElement.appendChild(fileElement);
			}
			getAlbumRootElement().appendChild(resourcesElement);
			resourceListSaved = true;
		}
	}

	private void saveSnapshotMetadata() {
		if (!metadataSaved || isRecording()) {
					
			if (metadataSaved){
				// If metatdata is saved, it must be a live debug session so
				// we need to add a new snapshot to the snapshot list
				NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);
				assert snapMetaDataNode.item(0) != null;
				document.getDocumentElement().removeChild(snapMetaDataNode.item(0));
			}
			
			Element metadataElement = document.createElement(METADATA);

			Element albumElement = document.createElement(ALBUM);
			albumElement.setAttribute("albumName", this.getDisplayName());
			metadataElement.appendChild(albumElement);

			Element snapshotsElement = document.createElement(SNAPSHOT_LIST);
			metadataElement.appendChild(snapshotsElement);

			for (Snapshot snap : snapshotList) {
				Element snapshotMetadataElement = document.createElement(SNAPSHOT);
				if (snap.getSnapshotDisplayName().length() == 0) {
					snapshotMetadataElement.setAttribute("displayName", snap.getSnapshotFileName());
				} else {
					snapshotMetadataElement.setAttribute("displayName", snap.getSnapshotDisplayName());
				}
				if (snap.getCreationDate() != null) {
					snapshotMetadataElement.setAttribute("date", snap.getCreationDate().toString());
				} else {
					snapshotMetadataElement.setAttribute("date", "unknown");
				}

				snapshotMetadataElement.setAttribute("description", snap.getSnapshotDescription());
				snapshotMetadataElement.setAttribute("fileName", snap.getSnapshotFileName());				
				snapshotMetadataElement.setAttribute("referenceLocationSourceFile", snap.getReferenceLocationSourceFile());
				snapshotMetadataElement.setAttribute("referenceLocationLineNumber", String.valueOf(snap.getReferenceLocationLineNumber()));
				
				snapshotsElement.appendChild(snapshotMetadataElement);
			}
			getAlbumRootElement().appendChild(metadataElement);
			metadataSaved = true;
		}
	}

	@SuppressWarnings("unchecked")
	private void saveLaunchConfiguration() {
		if (!launchConfigSaved) {
			EDCLaunch launch = EDCLaunch.getLaunchForSession(getRecordingSessionID());
			try {
				Map<String, Object> map = launch.getLaunchConfiguration().getAttributes();
				Element launchElement = document.createElement(LAUNCH);
				launchType = launch.getLaunchConfiguration().getType().getIdentifier();
				launchName = launch.getLaunchConfiguration().getName();
				Integer count = launchNames.get(launchName);
				if (count == null) {
					launchNames.put(launchName, new Integer(0));
				}
				else {
					count = new Integer(count.intValue() + 1);
					launchNames.put(launchName, count);
					launchName += " (" + count.toString() + ")";
				}
				launchElement.setAttribute("type", launchType);
				launchElement.setAttribute("name", launchName);
				Element propsElement = SnapshotUtils.makeXMLFromProperties(document, map);
				launchElement.appendChild(propsElement);
				getAlbumRootElement().appendChild(launchElement);
			} catch (CoreException e) {
				EDCDebugger.getMessageLogger().logError(null, e);
			}
			launchConfigSaved = true;
		}
	}

	private static void addZipEntry(ZipOutputStream zipOut, IAlbumArchiveEntry entry, File file)
			throws FileNotFoundException, IOException {
		if (file.exists()) {
			if (file.isDirectory()) {
				for (File child : file.listFiles()) {
					addZipEntry(zipOut, entry, child);
				}
			} else {
				// Add ZIP entry to output stream.m
				String path = ""; //$NON-NLS-1$

				if (entry != null) {
					path = entry.createEntryName(file);
				} else {
					path = file.getName();
				}

				zipOut.putNextEntry(new ZipEntry(path));

				// Create a buffer for reading the files
				byte[] buf = new byte[1024];

				// Transfer bytes from the file to the ZIP file
				// and compress the files
				FileInputStream in = new FileInputStream(file);
				int len;
				while ((len = in.read(buf)) > 0) {
					zipOut.write(buf, 0, len);
				}

				// Complete the entry
				zipOut.closeEntry();
				in.close();
			}
		}
	}

	/**
	 * Create and write a full snapshot album from scratch
	 */
	private void saveAlbum(IProgressMonitor monitor) {

		IPath zipPath = getLocation();
		ZipOutputStream zipOut = null;
		try {
			SubMonitor progress = SubMonitor.convert(monitor, 2000 + (snapshotList.size() * 1000));
			progress.subTask("Saving album data");

			zipOut = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));

			zipOut.putNextEntry(new ZipEntry(ALBUM_DATA));

			saveResourceList();
			progress.worked(1000);
			saveSnapshotMetadata();
			progress.worked(1000);

			String xml = LaunchManager.serializeDocument(document);
			zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$
			zipOut.closeEntry();

			for (Snapshot snap : snapshotList) {
				zipOut.putNextEntry(new ZipEntry(snap.getSnapshotFileName()));
				snap.saveSnapshot(zipOut);
				progress.worked(1000);
			}

		} catch (Exception e) {
			EDCDebugger.getMessageLogger().logError(null, e);
		} finally {
			try {
				if (zipOut != null) {
					zipOut.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Create and write a full snapshot album from scratch
	 */
	private void saveResources(IProgressMonitor monitor) {

		IPath zipPath = getLocation();
		ZipOutputStream zipOut = null;
		try {
			// TODO: Here's we're just rewriting the entire album again
			// Need to just add the resources alone using proper utils
			zipOut = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));

			for (IPath path : files) {

				IAlbumArchiveEntry entry = new IAlbumArchiveEntry() {

					public String createEntryName(File file) {
						StringBuffer entryPath = new StringBuffer();

						entryPath.append("Resources/");

						IPath filepath = new Path(file.getAbsolutePath());

						String deviceName = filepath.getDevice();
						if (deviceName != null) {
							// Remove the : from the end
							entryPath.append(deviceName.substring(0, deviceName.length() - 1));
							entryPath.append("/");
						}
						
						String[] segments = filepath.segments();
						int numSegments = segments.length - 1;

						for (int i = 0; i < numSegments; i++) {
							entryPath.append(segments[i]);
							entryPath.append("/");
						}
						entryPath.append(file.getName());
						return entryPath.toString();
					}
				};
				addZipEntry(zipOut, entry, path.toFile());
				if (monitor != null) {
					monitor.worked(1);
				}
			}
			zipOut.putNextEntry(new ZipEntry(ALBUM_DATA));

			saveResourceList();
			saveSnapshotMetadata();

			String xml = LaunchManager.serializeDocument(document);
			zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$
			zipOut.closeEntry();

			for (Snapshot snap : snapshotList) {
				zipOut.putNextEntry(new ZipEntry(snap.getSnapshotFileName()));
				snap.saveSnapshot(zipOut);
			}

		} catch (Exception e) {
			EDCDebugger.getMessageLogger().logError(null, e);
		} finally {
			try {
				if (zipOut != null) {
					zipOut.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private String getDefaultAlbumName() {
		return getLaunchName();
	}

	public void saveAlbum(IPath path) throws TransformerException, IOException {
		String xml = LaunchManager.serializeDocument(document);
		File file = path.toFile();
		if (!file.exists()) {
			file.createNewFile();
		}
		FileOutputStream stream = new FileOutputStream(file);
		stream.write(xml.getBytes("UTF8")); //$NON-NLS-1$
		stream.close();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openSnapshot(int)
	 */
	public void openSnapshot(final int index) {

		final DsfSession session = DsfSession.getSession(sessionID);

		DsfRunnable openIt = new DsfRunnable() {
			public void run() {
				currentSnapshotIndex = index;
				try {
					loadAlbum(false);
				} catch (Exception e) {
					EDCDebugger.getMessageLogger().logError(null, e);
				}
				if (session != null && snapshotList.size() > index) {
					Snapshot snapshot = snapshotList.get(index);
					snapshot.open(session);
					// Fire the event
					for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {
						l.snapshotOpened(snapshot);
					}
				}
			}
		};

		if (session != null && session.getExecutor() != null)
		{
			if (session.getExecutor().isInExecutorThread())
				openIt.run();
			else
				session.getExecutor().execute(openIt);
		}

	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getCurrentSnapshotIndex()
	 */
	public int getCurrentSnapshotIndex() {
		return currentSnapshotIndex;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openNextSnapshot()
	 */
	public void openNextSnapshot() throws Exception {
		int nextIndex = currentSnapshotIndex + 1;
		if (nextIndex >= snapshotList.size())
			nextIndex = 0;
		openSnapshot(nextIndex);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openPreviousSnapshot()
	 */
	public void openPreviousSnapshot() throws Exception {
		int previousIndex = currentSnapshotIndex - 1;
		if (previousIndex < 0)
			previousIndex = snapshotList.size() - 1;
		openSnapshot(previousIndex);
	}

	public void loadAlbum(boolean force) throws ParserConfigurationException, SAXException, IOException {
		if (force)
			loaded = false;
		if (!loaded) {
			File albumFile = location.toFile();
			setName(albumFile.getName());
			
			if (!isRecording()){
				// not creating the snapshot, so must be snapshot play back	
				try {
					ZipFileUtils.unzipFiles(albumFile, getAlbumRootDirectory().toOSString(), new NullProgressMonitor());
				} catch (Exception e) {
					EDCDebugger.getMessageLogger().logError(null, e);
				}
			}

			BufferedInputStream stream = ZipFileUtils.openFile(albumFile, ALBUM_DATA, DSA_FILE_EXTENSIONS);
			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			parser.setErrorHandler(new DefaultHandler());
			InputSource inputSource = new InputSource(stream);
			inputSource.setSystemId(albumFile.toURI().toString());	// avoid NPE inside XML parser
			setDocument(parser.parse(inputSource));

			loadAlbumInfo();
			loadLaunchConfiguration();
			loadResourceList();
			try {
				loadSnapshotMetadata();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				loaded = true;
				ZipFileUtils.unmount();
			}
		}
	}

	/**
	 * A lightwieght parse to get basic album info and what snapshots are
	 * available.
	 * 
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	public void loadAlbumMetada(boolean force) throws Exception {
		if (force)
			metaDataLoaded = false;
		if (!metaDataLoaded) {
			
			File albumFile = location.toFile();
			setDisplayName(albumFile.getName());

			BufferedInputStream stream = null;
			try {
				stream = ZipFileUtils.openFile(albumFile, ALBUM_DATA, DSA_FILE_EXTENSIONS);
				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				parser.setErrorHandler(new DefaultHandler());
				setDocument(parser.parse(new InputSource(stream)));
				loadSnapshotMetadata();
				loadLaunchConfiguration(); // need to load launch config in case we need to delete it

			} catch (Exception e) {
				EDCDebugger.getMessageLogger().logError("Failed to load album: " + getName(), e);
			} finally {
				metaDataLoaded = true;
				ZipFileUtils.unmount();
			}
		}
	}

	private void loadAlbumInfo() {
		document.getElementsByTagName(INFO).item(0);
	}

	private void setDocument(Document newDoc)
	{
		document = newDoc;
		albumRootElement = null;
	}
	
	private Element getAlbumRootElement()
	{
		if (albumRootElement == null)
		{
			NodeList albumRootElements = document.getElementsByTagName(ALBUM);
			if (albumRootElements.getLength() == 0)
			{
				albumRootElement = document.createElement(ALBUM);
				document.appendChild(albumRootElement);
			}
			else
			{
				albumRootElement = (Element) albumRootElements.item(0);
			}
		}
		return albumRootElement;
	}
	
	private void loadResourceList() {
		NodeList resources = document.getElementsByTagName(RESOURCES);
		NodeList elementFiles = ((Element) resources.item(0)).getElementsByTagName(FILE);
		int numFiles = elementFiles.getLength();
		for (int i = 0; i < numFiles; i++) {
			Element fileElement = (Element) elementFiles.item(i);
			String elementPath = fileElement.getAttribute("path");
			files.add(PathUtils.createPath(elementPath));		// for cross-created snapshot
		}
	}

	private void loadSnapshotMetadata() throws Exception {
		snapshotList.clear();
		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);

		if (snapMetaDataNode.getLength() == 0) {
			throw new Exception("Invalid or corrupted Album : " + getName());
		}
		NodeList albumNameElement = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(ALBUM);
		Element albumElement = (Element) albumNameElement.item(0);
		String albumDisplayName = albumElement.getAttribute("albumName");

		setDisplayName(albumDisplayName);

		NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);
		int numSnapshots = elementSnapshots.getLength();
		for (int i = 0; i < numSnapshots; i++) {
			Element snapshotElement = (Element) elementSnapshots.item(i);
			String elementDescription = snapshotElement.getAttribute("description");
			String elementDate = snapshotElement.getAttribute("date");
			String elementDispalyName = snapshotElement.getAttribute("displayName");
			String elementFileName = snapshotElement.getAttribute("fileName");
			String referenceLocationSourceFile = snapshotElement.getAttribute("referenceLocationSourceFile");
			String referenceLocationLineNumber = snapshotElement.getAttribute("referenceLocationLineNumber");
			
			Snapshot s = new Snapshot(this);
			s.setCreationDate(elementDate);
			s.setSnapshotFileName(elementFileName);
			s.setSnapshotDisplayName(elementDispalyName);
			s.setSnapshotDescription(elementDescription);
			if (referenceLocationLineNumber.length() > 0){
				s.setReferenceLocationLineNumber(Long.parseLong(referenceLocationLineNumber));
			}
			s.setReferenceLocationSourceFile(referenceLocationSourceFile);
			snapshotList.add(s);
		}
	}

	private void loadLaunchConfiguration() {
		NodeList launchElements = document.getElementsByTagName(LAUNCH);
		Element launchElement = (Element) launchElements.item(0);
		if (launchElement == null){
			return;
		}
		launchType = launchElement.getAttribute("type");
		launchName = launchElement.getAttribute("name");

		Element propElement = (Element) launchElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
		launchProperties = new HashMap<String, Object>();
		try {
			SnapshotUtils.initializeFromXML(propElement, launchProperties);
		} catch (Exception e) {
			EDCDebugger.getMessageLogger().logError(null, e);
		}

	}

	@SuppressWarnings("rawtypes")
	@Override
	public Object getAdapter(Class adapter) {
		if (adapter.equals(Document.class))
			return document;

		return super.getAdapter(adapter);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getAlbumRootDirectory()
	 */
	public IPath getAlbumRootDirectory() {
		if (albumRootDirectory == null) {
			IPath path = EDCDebugger.getDefault().getStateLocation().append("SnapshotAlbums");
			String locationName = location.lastSegment();
			int extension = locationName.lastIndexOf(".");
			if (extension > 0) {
				locationName = locationName.substring(0, extension);
			}
			path = path.append(locationName);
			File dir = path.toFile();
			if (!dir.exists()) {
				dir.mkdirs();
			}
			albumRootDirectory = path;
		}
		return albumRootDirectory;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchTypeID()
	 */
	public String getLaunchTypeID() {
		return launchType;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchProperties()
	 */
	public HashMap<String, Object> getLaunchProperties() {
		return launchProperties;
	}

	public void setLaunchProperties(HashMap<String, Object> launchProperties) {
		this.launchProperties = launchProperties;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchName()
	 */
	public String getLaunchName() {
		return launchName;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#playSnapshots(org.eclipse.cdt.dsf.service.DsfSession)
	 */
	public void playSnapshots() {
		if (!isPlayingSnapshots())
		{
			Job playSnapshotsJob = new Job("Play Snapshots for Album " + getDisplayName()){

				@Override
				protected IStatus run(IProgressMonitor monitor) {
					try {
						monitor.beginTask("Play Snapshots for Album " + getDisplayName(), IProgressMonitor.UNKNOWN);
						while (isPlayingSnapshots() && !monitor.isCanceled())
						{
							Album.this.openNextSnapshot();
							Thread.sleep(getPlaySnapshotInterval());
						}
						setPlayingSnapshots(false);
						monitor.done();
					} catch (Exception e) {
						EDCDebugger.getMessageLogger().logError(null, e);
						return new Status(Status.ERROR, EDCDebugger.PLUGIN_ID, null, e);
					}
					return Status.OK_STATUS;
				}
				
			};
			setPlayingSnapshots(true);
			playSnapshotsJob.schedule();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#addFile(org.eclipse.core.runtime.IPath)
	 */
	public void addFile(IPath path) {
		files.add(path);
	}

	public static Album getAlbumByLocation(IPath path) {
		return albumsByLocation.get(path);
	}

	public static IAlbum getAlbumBySession(String sessionId) {
		return albumsBySessionID.get(sessionId);
	}

	public static Album getRecordingForSession(String sessionId) {
		return albumsRecordingBySessionID.get(sessionId);
	}

	public void setLocation(IPath albumPath) {
		this.location = albumPath;
		albumsByLocation.put(albumPath, this);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLocation()
	 */
	public IPath getLocation() {
		return location;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#configureSourceLookupDirector(org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector)
	 */
	public void configureSourceLookupDirector(ISourceLookupDirector director) {
		MappingSourceContainer sourceContainer = new MappingSourceContainer(getName());
		configureMappingSourceContainer(sourceContainer);
		ArrayList<ISourceContainer> containers = new ArrayList<ISourceContainer>(Arrays.asList(director
				.getSourceContainers()));
		containers.add(sourceContainer);

		DirectorySourceContainer directoryContainer = new DirectorySourceContainer(getResourcesDirectory(), true);
		containers.add(directoryContainer);

		director.setSourceContainers(containers.toArray(new ISourceContainer[containers.size()]));
	}

	protected IPath getResourcesDirectory()
	{
		return getAlbumRootDirectory().append("Resources");
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#configureMappingSourceContainer(org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer)
	 */
	public void configureMappingSourceContainer(MappingSourceContainer mappingContainer) {
		IPath albumRoot = getResourcesDirectory();
		List<MapEntrySourceContainer> containers = new ArrayList<MapEntrySourceContainer>();
		Set<String> devicesAlreadyAdded = new HashSet<String>();
		String deviceName = null;
		for (IPath iPath : files) {
		    	deviceName = iPath.getDevice();
			if (deviceName != null && !devicesAlreadyAdded.contains(deviceName))
			{
				String albumRootSuffix = deviceName;
                if (albumRootSuffix.endsWith(":"))
                	albumRootSuffix = albumRootSuffix.substring(0, albumRootSuffix.length() - 1);
	                        devicesAlreadyAdded.add(deviceName);
                            MapEntrySourceContainer newContainer = new MapEntrySourceContainer(PathUtils.createPath(deviceName), albumRoot.append(albumRootSuffix));
                            containers.add(newContainer);
                                
			}
		}
		mappingContainer.addMapEntries(containers.toArray(new MapEntrySourceContainer[containers.size()]));
	}

	public static void setVariableCaptureDepth(int newSetting) {
		IEclipsePreferences scope = InstanceScope.INSTANCE.getNode(EDCDebugger.PLUGIN_ID);
		scope.putInt(PREF_VARIABLE_CAPTURE_DEPTH, newSetting);
		try {
			scope.flush();
		} catch (BackingStoreException e) {
			EDCDebugger.getMessageLogger().logError(null, e);
		}
	}

	public static int getVariableCaptureDepth() {
		return Platform.getPreferencesService().getInt(EDCDebugger.PLUGIN_ID,
				PREF_VARIABLE_CAPTURE_DEPTH, 5, null);
	}

	public static void setPlaySnapshotInterval(int delayInMilliseconds) {
		IEclipsePreferences scope = InstanceScope.INSTANCE.getNode(EDCDebugger.PLUGIN_ID);
		scope.putInt(PLAY_SNAPSHOT_DELAY_TIME, delayInMilliseconds);
		try {
			scope.flush();
		} catch (BackingStoreException e) {
			EDCDebugger.getMessageLogger().logError(null, e);
		}
	}

	public static int getPlaySnapshotInterval() {
		return Platform.getPreferencesService().getInt(EDCDebugger.PLUGIN_ID,
				PLAY_SNAPSHOT_DELAY_TIME, 5000, null);
	}

	public static void setSnapshotCreationControl(String newSetting) {
		IEclipsePreferences scope = InstanceScope.INSTANCE.getNode(EDCDebugger.PLUGIN_ID);
		scope.put(PREF_CREATION_CONTROL, newSetting);
		try {
			scope.flush();
		} catch (BackingStoreException e) {
			EDCDebugger.getMessageLogger().logError(null, e);
		}
	}

	public static String getSnapshotCreationControl() {
		return Platform.getPreferencesService().getString(EDCDebugger.PLUGIN_ID,
				PREF_CREATION_CONTROL, CREATE_MANUAL, null);
	}

	protected static void playSnapshotSound() {
		Bundle bundle = Platform.getBundle(EDCDebugger.getUniqueIdentifier());
		if (bundle == null)
			return;
		
		URL url = null;
		try {
			url = FileLocator.toFileURL(bundle.getEntry(CAMERA_CLICK_WAV));
		} catch (IOException e) {
		} catch (RuntimeException e){
		}
		finally {
			if (url != null){
				File f = new File(url.getFile());
				SnapshotUtils.playSoundFile(f);
			}
		}
		
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getSnapshots()
	 */
	public List<Snapshot> getSnapshots() {
		if (snapshotList == null || snapshotList.size() == 0) {
			try {
				loadAlbumMetada(false);
			} catch (Exception e) {
				EDCDebugger.getMessageLogger().logError("Failed to load snapshots", e);
			}
		}

		return snapshotList;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#isLoaded()
	 */
	public boolean isLoaded() {
		return loaded;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getIndexOfSnapshot(org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot)
	 */
	public int getIndexOfSnapshot(Snapshot snap) {
		return snapshotList.indexOf(snap);
	}

	public void setCurrentSnapshotIndex(int index) {
		if (currentSnapshotIndex >= 0 && currentSnapshotIndex < snapshotList.size()) {
			currentSnapshotIndex = index;
		}
	}

	/**
	 * Update album.xml within the Album's .dsa file with new Snapshot data
	 * 
	 * @param albumName
	 *            - Name of album to display. Use null if value should not be
	 *            updated.
	 * @param snap
	 *            - Specific snapshot to update. Use null is snapshot should not
	 *            be updated.
	 */
	public void updateSnapshotMetaData(String albumName, Snapshot snap) {
		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);
		
		// try to update album display name
		if (albumName != null) {
			NodeList albumNameNode = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(ALBUM);
			((Element) albumNameNode.item(0)).setAttribute("albumName", albumName);
		}

		// try to update snapshot data
		if (snap != null) {

			NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);

			int numSnapshots = elementSnapshots.getLength();
			for (int i = 0; i < numSnapshots; i++) {
				Element currentSnapshotNode = (Element) elementSnapshots.item(i);
				String fileName = currentSnapshotNode.getAttribute("fileName");
				if (fileName.equals(snap.getSnapshotFileName())) {

					currentSnapshotNode.setAttribute("description", snap.getSnapshotDescription());
					currentSnapshotNode.setAttribute("displayName", snap.getSnapshotDisplayName());

					break;
				}
			}
		}

		saveAlbumData();

		// refresh all data
		try {
			loadAlbumMetada(true);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void saveAlbumData() {
		try {
			File tempFile = File.createTempFile("album", ".xml");
			File tempFile2 = new File(tempFile.getParent() + File.separator + ALBUM_DATA);
			tempFile.delete();
			if (!tempFile2.exists()) {
				tempFile2.delete();
			}
			tempFile2.createNewFile();
			saveAlbum(new Path(tempFile2.toString()));
			File[] fileList = { tempFile2 };
			ZipFileUtils.addFilesToZip(fileList, getLocation().toFile(), DSA_FILE_EXTENSIONS);

		} catch (IOException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#deleteSnapshot(org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot)
	 */
	public void deleteSnapshot(Snapshot snap) {

		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);

		NodeList elementSnapshotList = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT_LIST);
		NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);

		int numSnapshots = elementSnapshots.getLength();
		for (int i = 0; i < numSnapshots; i++) {
			Element currentSnapshotNode = (Element) elementSnapshots.item(i);
			String fileName = currentSnapshotNode.getAttribute("fileName");
			if (fileName.equals(snap.getSnapshotFileName())) {
				elementSnapshotList.item(0).removeChild(currentSnapshotNode);
				break;
			}
		}

		snapshotList.remove(snap);

		saveAlbumData();

		// refresh all data
		try {
			loadAlbum(true);
			loadAlbumMetada(true);
		} catch (Exception e) {

		}

		ZipFileUtils.deleteFileFromZip(snap.getSnapshotFileName(), getLocation().toFile(), DSA_FILE_EXTENSIONS);
	}

	@Override
	public String toString() {
		return "Album [name=" + name + ", launchName=" + launchName + ", sessionID=" + sessionID + "]";
	}
	
	public IPath createEmptyAlbum() {
		IPath zipPath = null;
		try {
			zipPath = SnapshotUtils.getSnapshotsProject().getLocation();
			zipPath = zipPath.append(getDefaultAlbumName());
			zipPath = zipPath.addFileExtension("dsa");
			boolean created =  ZipFileUtils.createNewZip(zipPath.toFile());
			
			if (created && zipPath.toFile().exists()){
				setLocation(zipPath);
			} else {
				return null;
			}
			SnapshotUtils.getSnapshotsProject().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
		} catch (CoreException e) {
			EDCDebugger.getMessageLogger().logError(e.getLocalizedMessage(), e);
		}		
		return zipPath;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#isRecording()
	 */
	public boolean isRecording() {
		return recordingSessionID.length() > 0;
	}

	/**
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public static void addSnapshotAlbumEventListener(ISnapshotAlbumEventListener listener) {
		listeners.add(listener);
	}
	
	/**
	 * @noreference This method is not intended to be referenced by clients.
	 */
	public static void removeSnapshotAlbumEventListener(ISnapshotAlbumEventListener listener) {
		listeners.remove(listener);
	}

	public static void captureSnapshotForSession(final DsfSession session) {
		Job createSnapshotJob = new Job("Creating Debug Snapshot") {

			@Override
			protected IStatus run(final IProgressMonitor monitor) {

				Query<IFrameDMContext> frameQuery = new Query<IFrameDMContext>() {
					@Override
					protected void execute(
							DataRequestMonitor<IFrameDMContext> rm) {
						DsfServicesTracker servicesTracker = new DsfServicesTracker(
								EDCDebugger.getBundleContext(),
								session.getId());
						try {
							RunControl runControl = servicesTracker.getService(RunControl.class);
							IThreadDMContext[] suspendedThreads = runControl.getSuspendedThreads();
							if (suspendedThreads.length == 0)
							{
								rm.setData(null);
								rm.done();
							}
							else
							{
								Stack stackService = servicesTracker.getService(Stack.class);
								if (stackService != null) {
									stackService.getTopFrame(suspendedThreads[0], rm);
								}
							}
						} finally {
							servicesTracker.dispose();
						}
					}
				};

				session.getExecutor().execute(frameQuery);

				IStatus status = Status.OK_STATUS;
				try {
					final StackFrameDMC stackFrame = (StackFrameDMC) frameQuery.get();

					String sessionId = session.getId();
					Album album = Album.getRecordingForSession(sessionId);
					if (album == null) {
						album = new Album();
						album.setRecordingSessionID(sessionId);
					}
					final Album finalAlbum = album;
					playSnapshotSound();

					Query<IStatus> query = new Query<IStatus>() {
						@Override
						protected void execute(final DataRequestMonitor<IStatus> drm) {
							try {
								Snapshot newSnapshot = finalAlbum.createSnapshot(session, stackFrame, monitor);
								// Fire the event to anyone listening
								for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {
									l.snapshotCreated(finalAlbum, newSnapshot, session, stackFrame);
								}
								drm.setData(Status.OK_STATUS);
							} catch (Exception e) {
								Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "Error creating snapshot.", e);
								EDCDebugger.getMessageLogger().log(s);
								drm.setStatus(s);
							}
							drm.done();
						}
					};

					session.getExecutor().execute(query);

					status = query.get();
				} catch (Exception e) {
					status = new Status(Status.ERROR, EDCDebugger.PLUGIN_ID, "Error creating snapshot", e);
				}

				return status;
			}
		};

		createSnapshotJob.schedule();
	}

    public boolean isPlayingSnapshots() {
		return playingSnapshots;
	}

	public void setPlayingSnapshots(boolean playingSnapshots) {
		this.playingSnapshots = playingSnapshots;
	}

	public void stopPlayingSnapshots() {
		setPlayingSnapshots(false);
		openSnapshot(getCurrentSnapshotIndex()); // Reloading the current snapshot will resync the UI.
	}

}
