/*******************************************************************************
 * Copyright (c) 2004, 2015 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.jdt.internal.debug.ui.monitors;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;

/**
 * Manager for the thread and monitor model.
 */
public class ThreadMonitorManager implements IDebugEventSetListener, IPropertyChangeListener {

	private static ThreadMonitorManager fDefaultManager;

	/**
	 * HashMap IJavaThread -> JavaMonitorThread
	 */
	private HashMap<IDebugElement, Object> fJavaMonitorThreads;
	/**
	 * HashMap IJavaObject -> JavaMonitor
	 */
	private HashMap<IDebugElement, Object> fJavaMonitors;

	private boolean fIsEnabled;

	/**
	 * Returns the default ThreadMonitorManager object.
	 */
	public static ThreadMonitorManager getDefault() {
		if (fDefaultManager == null) {
			fDefaultManager= new ThreadMonitorManager();
		}
		return fDefaultManager;
	}

	private ThreadMonitorManager() {
		fJavaMonitorThreads= new HashMap<>();
		fJavaMonitors= new HashMap<>();
		IPreferenceStore preferenceStore = JDIDebugUIPlugin.getDefault().getPreferenceStore();
		preferenceStore.addPropertyChangeListener(this);
		fIsEnabled= preferenceStore.getBoolean(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO);
		if (fIsEnabled) {
			DebugPlugin.getDefault().addDebugEventListener(this);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent[])
	 */
	@Override
	public void handleDebugEvents(DebugEvent[] events) {
		for (int i= 0; i < events.length; i++) {
			DebugEvent debugEvent= events[i];
			Object eventSource= debugEvent.getSource();
			int eventKind= debugEvent.getKind();
			IJavaThread javaThread = null;
			if (eventSource instanceof IAdaptable) {
				IAdaptable adaptable = (IAdaptable)eventSource;
				javaThread = adaptable.getAdapter(IJavaThread.class);
				if (javaThread != null) {
					switch (eventKind) {
						case DebugEvent.SUSPEND:
						case DebugEvent.RESUME:
							// refresh on suspend/resume
							if (debugEvent.getDetail() != DebugEvent.EVALUATION_IMPLICIT) {
								handleSuspendResume();
							}
							break;
						case DebugEvent.TERMINATE:
							// clean the thread map when a thread terminates
							handleThreadTerminate(javaThread);
							break;
					}
				} else {
					IJavaDebugTarget target = adaptable.getAdapter(IJavaDebugTarget.class);
					if (target != null) {
						switch (eventKind) {
							case DebugEvent.SUSPEND:
							case DebugEvent.RESUME:
								// refresh on suspend/resume
								if (debugEvent.getDetail() != DebugEvent.EVALUATION_IMPLICIT) {
									handleSuspendResume();
								}
								break;
							case DebugEvent.TERMINATE:
								// clean the maps when a target terminates
								handleDebugTargetTerminate(target);
								break;
						}
					}
				}
			}
		}
	}

	private void handleSuspendResume() {
		JavaMonitorThread[] threads = getJavaMonitorThreads();
		for (int i = 0; i < threads.length; i++) {
			threads[i].setToUpdate();
		}
		DebugPlugin.getDefault().asyncExec(new RefreshAndDetectDeadlock());
	}

	private void handleThreadTerminate(IJavaThread thread) {
		// remove this thread
		synchronized(fJavaMonitorThreads) {
			fJavaMonitorThreads.remove(thread);
		}
	}

	private void handleDebugTargetTerminate(IJavaDebugTarget debugTarget) {
		// remove the threads and monitors for this debug target.
		clean(fJavaMonitors, debugTarget);
		clean(fJavaMonitorThreads, debugTarget);
	}

	private void clean(Map<IDebugElement, Object> map, IJavaDebugTarget debugTarget) {
		IDebugElement debugElements[] = null;
		synchronized(map) {
			debugElements = new IDebugElement[map.size()];
			debugElements =	map.keySet().toArray(debugElements);
		}
		for(int i = 0; i < debugElements.length; ++i) {
			if (debugElements[i].getDebugTarget().equals(debugTarget)) {
				synchronized(map) {
					map.remove(debugElements[i]);
				}
			}
		}
	}

	/**
	 * Returns the unique JavaMonitorThread object for the given thread.
	 */
	protected JavaMonitorThread getJavaMonitorThread(IJavaThread thread, IThread originalThread) {
		synchronized (fJavaMonitorThreads) {
			JavaMonitorThread javaMonitorThread= (JavaMonitorThread) fJavaMonitorThreads.get(thread);
			if (javaMonitorThread == null) {
				javaMonitorThread= new JavaMonitorThread(thread, originalThread);
				fJavaMonitorThreads.put(thread, javaMonitorThread);
				DebugPlugin.getDefault().asyncExec(new DetectDeadlock());
			} else if (originalThread != null) {
				javaMonitorThread.setOriginalThread(originalThread);
			}
			return javaMonitorThread;
		}
	}

	/**
	 * Returns the unique JavaMonitor object for the given monitor.
	 */
	protected JavaMonitor getJavaMonitor(IJavaObject monitor) {
		synchronized (fJavaMonitors) {
			JavaMonitor javaMonitor= (JavaMonitor) fJavaMonitors.get(monitor);
			if (javaMonitor == null) {
				javaMonitor= new JavaMonitor(monitor);
				fJavaMonitors.put(monitor, javaMonitor);
			}
			return javaMonitor;
		}
	}

	/**
	 * Removes a monitor from the monitor map.
	 */
	protected void removeJavaMonitor(JavaMonitor monitor) {
		synchronized(fJavaMonitors) {
			fJavaMonitors.remove(monitor.getMonitor());
		}
	}

	/**
	 * Returns the monitor the given thread is waiting for.
	 */
	public JavaContendedMonitor getContendedMonitor(IThread thread) {
        IJavaThread javaThread = thread.getAdapter(IJavaThread.class);
		if (javaThread == null || !fIsEnabled || !((IJavaDebugTarget)javaThread.getDebugTarget()).supportsMonitorInformation()) {
			return null;
		}
		return getJavaMonitorThread(javaThread, thread).getContendedMonitor();
	}

	/**
	 * Returns the monitors the given thread owns.
	 */
	public JavaOwnedMonitor[] getOwnedMonitors(IThread thread) {
        IJavaThread javaThread = thread.getAdapter(IJavaThread.class);
    	if (javaThread == null || !fIsEnabled || !((IJavaDebugTarget)javaThread.getDebugTarget()).supportsMonitorInformation()) {
    		return new JavaOwnedMonitor[0];
    	}
    	return getJavaMonitorThread(javaThread, thread).getOwnedMonitors();
	}

	/**
	 *  Runnable to be run asynchronously, to refresh the model and
	 *  look for deadlocks.
	 */
	class RefreshAndDetectDeadlock extends DetectDeadlock {
		@Override
		public void run() {
			JavaMonitorThread[] threads= getJavaMonitorThreads();
			for (int i = 0; i < threads.length; i++) {
				threads[i].refresh();
			}
			super.run();
		}
	}

	class DetectDeadlock implements Runnable {
		@Override
		public void run() {
			JavaMonitorThread[] threads= getJavaMonitorThreads();
			JavaMonitor[] monitors= getJavaMonitors();
			List<Object> inDeadlock= new ArrayList<>();
			for (int i = 0; i < threads.length; i++) {
				JavaMonitorThread thread= threads[i];
				List<JavaMonitorThread> threadStack= new ArrayList<>();
				List<JavaMonitor> monitorStack= new ArrayList<>();
				while (thread != null) {
					boolean isInDeadlock= false;
					if (inDeadlock.contains(thread) || threadStack.contains(thread)) {
						isInDeadlock= true;
					} else {
						JavaMonitor monitor = thread.getContendedMonitor0();
						if (monitor == null) {
							thread= null;
						} else if (inDeadlock.contains(monitor)) {
							isInDeadlock= true;
						} else {
							threadStack.add(thread);
							monitorStack.add(monitor);
							thread= monitor.getOwningThread0();
						}
					}
					if (isInDeadlock) {
						// is in a deadlock, set the elements of the back trace as 'in a deadlock'
						for (Iterator<JavaMonitorThread> iter = threadStack.iterator(); iter.hasNext();) {
							inDeadlock.add(iter.next());
						}
						for (Iterator<JavaMonitor> iter = monitorStack.iterator(); iter.hasNext();) {
							inDeadlock.add(iter.next());
						}
						thread= null;
					}
				}
			}
			for (int i = 0; i < threads.length; i++) {
				JavaMonitorThread thread= threads[i];
				thread.setInDeadlock(inDeadlock.contains(thread));
			}
			for (int i = 0; i < monitors.length; i++) {
				JavaMonitor monitor= monitors[i];
				monitor.setInDeadlock(inDeadlock.contains(monitor));
			}
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
	 */
	@Override
	public void propertyChange(PropertyChangeEvent event) {
		if (event.getProperty().equals(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO)) {
			fIsEnabled= JDIDebugUIPreferenceInitializer.getBoolean(event);
			if (fIsEnabled) {
				DebugPlugin.getDefault().addDebugEventListener(this);
			} else {
				DebugPlugin.getDefault().removeDebugEventListener(this);
			}
		}
	}

	/**
	 * Returns <code>true</code> if SHOW_MONITOR_THREAD_INFO is on and the given thread is
	 * in a deadlock, <code>false</code> otherwise.
	 */
	public boolean isInDeadlock(IThread thread) {
        IJavaThread javaThread = thread.getAdapter(IJavaThread.class);
		if (!fIsEnabled || !((IJavaDebugTarget)javaThread.getDebugTarget()).supportsMonitorInformation()) {
			return false;
		}
		return getJavaMonitorThread(javaThread, thread).isInDeadlock();
	}

	private JavaMonitor[] getJavaMonitors() {
		synchronized(fJavaMonitors) {
			JavaMonitor[] monitors = new JavaMonitor[fJavaMonitors.size()];
			return fJavaMonitors.values().toArray(monitors);
		}
	}

	private JavaMonitorThread[] getJavaMonitorThreads() {
		synchronized(fJavaMonitorThreads) {
			JavaMonitorThread[] threads = new JavaMonitorThread[fJavaMonitorThreads.size()];
			return fJavaMonitorThreads.values().toArray(threads);
		}
	}
}
