/*******************************************************************************
 * Copyright (c) 2004, 2018 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
 *     Justin Kong (IBM) -  Bug 258890 -  [Memory View] MemoryViewSynchronizationService not implementing addPropertyChangeListener() correctly
 *******************************************************************************/
package org.eclipse.debug.internal.ui.views.memory;

import java.math.BigInteger;
import java.util.Enumeration;
import java.util.Hashtable;

import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.debug.core.IMemoryBlockListener;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.ui.memory.IMemoryRendering;
import org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Display;

/**
 * Synchronization service for the memory view.
 *
 * @since 3.1
 */
public class MemoryViewSynchronizationService implements IMemoryRenderingSynchronizationService, IMemoryBlockListener, IPropertyChangeListener {

	private static final int ENABLED = 0;
	private static final int ENABLING = 1;
	private static final int DISABLED = 2;

	private Hashtable<IMemoryBlock, SynchronizeInfo> fSynchronizeInfo;
	private int fEnableState = ENABLED;
	private Hashtable<IPropertyChangeListener, PropertyListener> fPropertyListeners;

	private IMemoryRendering fLastChangedRendering;
	private IMemoryRendering fSyncServiceProvider;

	private static final boolean DEBUG_SYNC_SERVICE = false;

	public MemoryViewSynchronizationService() {
		fSynchronizeInfo = new Hashtable<>();
		fPropertyListeners = new Hashtable<>();
		MemoryViewUtil.getMemoryBlockManager().addListener(this);
	}

	/**
	 * Wrapper for ISynchronizedMemoryBlockView Holds a list of property filters
	 * for the view.
	 */
	class PropertyListener {
		IPropertyChangeListener fListener;
		String[] fFilters;

		public PropertyListener(IPropertyChangeListener listener, String[] properties) {
			fListener = listener;

			if (properties != null) {
				fFilters = properties;
			}
		}

		/**
		 * If the property matches one of the filters, the property is valid and
		 * the view should be notified about its change.
		 *
		 * @param property the property
		 * @return if the property is specified in the filter
		 */
		public boolean isValidProperty(String property) {
			if (fFilters == null) {
				return true;
			}
			for (int i = 0; i < fFilters.length; i++) {
				if (fFilters[i].equals(property)) {
					return true;
				}
			}
			return false;
		}

		/**
		 * Set property filters, indicating what property change events the
		 * listener is interested in.
		 *
		 * @param filters the property filters or <code>null</code>
		 */
		public void setPropertyFilters(String[] filters) {
			fFilters = filters;
		}

		/**
		 * @return Returns the fListener.
		 */
		public IPropertyChangeListener getListener() {
			return fListener;
		}
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.eclipse.debug.ui.IMemoryBlockViewSynchronizer#getSynchronizedProperty
	 * (org.eclipse.debug.ui.ISynchronizedMemoryBlockView, java.lang.String)
	 */
	public Object getSynchronizedProperty(IMemoryBlock memoryBlock, String propertyId) {
		SynchronizeInfo info = fSynchronizeInfo.get(memoryBlock);

		if (info != null) {
			Object value = info.getProperty(propertyId);
			return value;
		}

		return null;
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.eclipse.debug.ui.IMemoryBlockListener#MemoryBlockAdded(org.eclipse
	 * .debug.core.model.IMemoryBlock)
	 */
	@Override
	public void memoryBlocksAdded(IMemoryBlock[] memoryBlocks) {
		// do nothing when a memory block is added
		// create a synchronize info object when there is a fView
		// tab registered to be synchronized.

	}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.eclipse.debug.ui.IMemoryBlockListener#MemoryBlockRemoved(org.eclipse
	 * .debug.core.model.IMemoryBlock)
	 */
	@Override
	public void memoryBlocksRemoved(IMemoryBlock[] memoryBlocks) {

		// Sync info can be null if the service is already shut down
		if (fSynchronizeInfo == null) {
			return;
		}

		for (int i = 0; i < memoryBlocks.length; i++) {
			IMemoryBlock memory = memoryBlocks[i];

			if (fLastChangedRendering != null && fLastChangedRendering.getMemoryBlock() == memory) {
				fLastChangedRendering = null;
			}

			if (fSyncServiceProvider != null && fSyncServiceProvider.getMemoryBlock() == memory) {
				fSyncServiceProvider = null;
			}

			// delete the info object and remove it from fSynchronizeInfo
			// when the memory block is deleted
			SynchronizeInfo info = fSynchronizeInfo.get(memory);

			if (info != null) {
				info.delete();
				fSynchronizeInfo.remove(memory);
			}
		}
	}

	/**
	 * Clean up when the plug-in is shutdown
	 */
	public void shutdown() {
		if (fSynchronizeInfo != null) {
			Enumeration<SynchronizeInfo> enumeration = fSynchronizeInfo.elements();

			// clean up all synchronize info objects
			while (enumeration.hasMoreElements()) {
				SynchronizeInfo info = enumeration.nextElement();
				info.delete();
			}

			fSynchronizeInfo.clear();
			fSynchronizeInfo = null;
		}
		MemoryViewUtil.getMemoryBlockManager().removeListener(this);
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService#
	 * addPropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener,
	 * java.lang.String[])
	 */
	@Override
	public void addPropertyChangeListener(IPropertyChangeListener listener, String[] properties) {
		fPropertyListeners.put(listener, new PropertyListener(listener, properties));
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService#
	 * removePropertyChangeListener
	 * (org.eclipse.jface.util.IPropertyChangeListener)
	 */
	@Override
	public void removePropertyChangeListener(IPropertyChangeListener listener) {
		if (fPropertyListeners.containsKey(listener)) {
			fPropertyListeners.remove(listener);
		}
	}

	/**
	 * Fire property change events
	 *
	 * @param evt the event to fire
	 */
	public void firePropertyChanged(final PropertyChangeEvent evt) {
		// do not fire property changed event if the synchronization
		// service is disabled
		if (fEnableState == DISABLED) {
			return;
		}

		// Make sure the synchronizer does not swallow any events
		// Values of the properties are updated in the syncrhonizer immediately.
		// Change events are queued up on the UI Thread.
		Display.getDefault().syncExec(() -> {
			if (fSynchronizeInfo == null) {
				return;
			}

			IMemoryRendering rendering = (IMemoryRendering) evt.getSource();
			String propertyId = evt.getProperty();

			SynchronizeInfo info = fSynchronizeInfo.get(rendering.getMemoryBlock());
			if (info != null) {
				Object value = info.getProperty(propertyId);
				if (value != null) {
					Enumeration<PropertyListener> enumeration = fPropertyListeners.elements();

					while (enumeration.hasMoreElements()) {
						PropertyListener listener = enumeration.nextElement();

						IPropertyChangeListener origListener = listener.getListener();

						// if it's a valid property - valid means that it's
						// listed in the property filters
						if (listener.isValidProperty(propertyId)) {
							PropertyChangeNotifier notifier = new PropertyChangeNotifier(origListener, evt);
							SafeRunner.run(notifier);
						}
					}
				}
			}
		});
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService#
	 * getProperty(org.eclipse.debug.core.model.IMemoryBlock, java.lang.String)
	 */
	@Override
	public Object getProperty(IMemoryBlock block, String property) {

		// When the synchronization service is disabled
		// return null for all queries to properties
		// This is to ensure that renderings are not synchronized
		// to new synchronization properties when the sync service is
		// disabled.
		if (!isEnabled()) {
			return null;
		}

		SynchronizeInfo info = fSynchronizeInfo.get(block);

		if (info != null) {
			return info.getProperty(property);
		}

		return null;
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
	 * .jface.util.PropertyChangeEvent)
	 */
	@Override
	public void propertyChange(PropertyChangeEvent event) {
		if (event == null || !(event.getSource() instanceof IMemoryRendering)) {
			return;
		}

		// Do not handle any property changed event as the
		// sync service is being enabled.
		// Otherwise, current sync info provider may overwrite
		// sync info unexpectedly. We want to sync with the rendering
		// that is last changed.
		if (fEnableState == ENABLING) {
			return;
		}

		IMemoryRendering rendering = ((IMemoryRendering) event.getSource());
		IMemoryBlock memoryBlock = rendering.getMemoryBlock();
		String propertyId = event.getProperty();
		Object value = event.getNewValue();

		if (DEBUG_SYNC_SERVICE) {
			DebugUIPlugin.trace("SYNC SERVICE RECEIVED CHANGED EVENT:"); //$NON-NLS-1$
			DebugUIPlugin.trace("Source:  " + rendering); //$NON-NLS-1$
			DebugUIPlugin.trace("Property:  " + propertyId); //$NON-NLS-1$
			DebugUIPlugin.trace("Value:  " + value); //$NON-NLS-1$

			if (value instanceof BigInteger) {
				DebugUIPlugin.trace("Value in hex:  " + ((BigInteger) value).toString(16)); //$NON-NLS-1$
			}
		}

		if (memoryBlock == null) {
			return;
		}

		if (propertyId == null) {
			return;
		}

		// find the synchronize info object for the memory block
		SynchronizeInfo info = fSynchronizeInfo.get(memoryBlock);

		// if info is not available, need to create one to hold the property
		if (info == null) {
			info = new SynchronizeInfo(memoryBlock);
			fSynchronizeInfo.put(memoryBlock, info);
		}

		// get the value of the property
		Object oldValue = info.getProperty(propertyId);

		if (oldValue == null) {
			// if the value has never been added to the info object
			// set the property and fire a change event
			info.setProperty(propertyId, value);
			fLastChangedRendering = rendering;
			firePropertyChanged(event);
			return;
		} else if (!oldValue.equals(value)) {
			// if the value has changed
			// set the property and fire a change event
			info.setProperty(propertyId, value);
			fLastChangedRendering = rendering;
			firePropertyChanged(event);
		}
	}

	public void setEnabled(boolean enabled) {
		if (enabled && fEnableState == ENABLED) {
			return;
		}

		if (!enabled && fEnableState == DISABLED) {
			return;
		}

		try {
			if (enabled) {
				fEnableState = ENABLING;
				// get sync info from the sync service provider
				if (fLastChangedRendering != null) {
					IMemoryBlock memBlock = fLastChangedRendering.getMemoryBlock();
					SynchronizeInfo info = fSynchronizeInfo.get(memBlock);
					String[] ids = info.getPropertyIds();

					// stop handling property changed event while the
					// synchronization service is being enabled
					// this is to get around problem when the last changed
					// rendering is not currently the sync info provider

					for (int i = 0; i < ids.length; i++) {
						PropertyChangeEvent evt = new PropertyChangeEvent(fLastChangedRendering, ids[i], null, info.getProperty(ids[i]));
						firePropertyChanged(evt);
					}
				}
			}
		} finally {
			if (enabled) {
				fEnableState = ENABLED;
			} else {
				fEnableState = DISABLED;
			}
		}
	}

	public boolean isEnabled() {
		return fEnableState == ENABLED;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService#
	 * setSynchronizationProvider(org.eclipse.debug.ui.memory.IMemoryRendering)
	 */
	@Override
	public void setSynchronizationProvider(IMemoryRendering rendering) {

		if (DEBUG_SYNC_SERVICE) {
			DebugUIPlugin.trace("SYNCHRONIZATION PROVIDER: " + rendering); //$NON-NLS-1$
		}
		if (fSyncServiceProvider != null) {
			fSyncServiceProvider.removePropertyChangeListener(this);
		}
		if (rendering != null) {
			rendering.addPropertyChangeListener(this);
		}
		fSyncServiceProvider = rendering;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService#
	 * getSynchronizationProvider()
	 */
	@Override
	public IMemoryRendering getSynchronizationProvider() {
		return fSyncServiceProvider;
	}
}
