/*******************************************************************************
 * Copyright (c) 2004, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ant.internal.launching.debug.model;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IVariable;

/**
 * An Ant build thread.
 */
public class AntThread extends AntDebugElement implements IThread {

	static final IBreakpoint[] NO_BREAKPOINTS = new IBreakpoint[0];

	/**
	 * Breakpoints this thread is suspended at or <code>null</code> if none.
	 */
	private IBreakpoint[] fBreakpoints;

	/**
	 * The stackframes associated with this thread
	 */
	private List<AntStackFrame> fFrames = new ArrayList<>(1);

	/**
	 * The stackframes to be reused on suspension
	 */
	private List<AntStackFrame> fOldFrames;

	/**
	 * Whether this thread is stepping
	 */
	private boolean fStepping = false;

	private boolean fRefreshProperties = true;

	/**
	 * The user properties associated with this thread
	 */
	private AntProperties fUserProperties;

	/**
	 * The system properties associated with this thread
	 */
	private AntProperties fSystemProperties;

	/**
	 * The properties set during the build associated with this thread
	 */
	private AntProperties fRuntimeProperties;

	private Object fPropertiesLock = new Object();

	/**
	 * Constructs a new thread for the given target
	 * 
	 * @param target
	 *            the Ant Build
	 */
	public AntThread(AntDebugTarget target) {
		super(target);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IThread#getStackFrames()
	 */
	@Override
	public synchronized IStackFrame[] getStackFrames() throws DebugException {
		if (isSuspended()) {
			if (fFrames.isEmpty()) {
				getStackFrames0();
			}
		}

		return fFrames.toArray(new IStackFrame[fFrames.size()]);
	}

	/**
	 * Retrieves the current stack frames in the thread possibly waiting until the frames are populated
	 * 
	 */
	private void getStackFrames0() throws DebugException {
		synchronized (fFrames) {
			getAntDebugTarget().getStackFrames();
			if (fFrames.size() > 0) {
				// frames set..no need to wait
				return;
			}
			int attempts = 0;
			try {
				while (fFrames.isEmpty() && !isTerminated()) {
					fFrames.wait(50);
					if (attempts == 20 && fFrames.isEmpty() && !isTerminated()) {
						throwDebugException(DebugModelMessages.AntThread_3);
					}
					attempts++;
				}
			}
			catch (InterruptedException e) {
				// do nothing
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IThread#hasStackFrames()
	 */
	@Override
	public boolean hasStackFrames() throws DebugException {
		return isSuspended();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IThread#getPriority()
	 */
	@Override
	public int getPriority() throws DebugException {
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IThread#getTopStackFrame()
	 */
	@Override
	public synchronized IStackFrame getTopStackFrame() throws DebugException {
		if (isSuspended()) {
			if (fFrames.isEmpty()) {
				getStackFrames0();
			}
			if (fFrames.size() > 0) {
				return fFrames.get(0);
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IThread#getName()
	 */
	@Override
	public String getName() {
		return "Thread [Ant Build]"; //$NON-NLS-1$
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IThread#getBreakpoints()
	 */
	@Override
	public IBreakpoint[] getBreakpoints() {
		if (fBreakpoints == null) {
			return NO_BREAKPOINTS;
		}
		return fBreakpoints;
	}

	/**
	 * Sets the breakpoints this thread is suspended at, or <code>null</code> if none.
	 * 
	 * @param breakpoints
	 *            the breakpoints this thread is suspended at, or <code>null</code> if none
	 */
	protected void setBreakpoints(IBreakpoint[] breakpoints) {
		fBreakpoints = breakpoints;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
	 */
	@Override
	public boolean canResume() {
		return isSuspended();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
	 */
	@Override
	public boolean canSuspend() {
		return !isSuspended();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
	 */
	@Override
	public boolean isSuspended() {
		return getDebugTarget().isSuspended();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.ISuspendResume#resume()
	 */
	@Override
	public synchronized void resume() throws DebugException {
		aboutToResume(DebugEvent.CLIENT_REQUEST, false);
		getDebugTarget().resume();
	}

	/**
	 * Call-back when the target is resumed
	 * 
	 * @since 1.0
	 */
	void resumedByTarget() {
		aboutToResume(DebugEvent.CLIENT_REQUEST, false);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
	 */
	@Override
	public synchronized void suspend() throws DebugException {
		getDebugTarget().suspend();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IStep#canStepInto()
	 */
	@Override
	public boolean canStepInto() {
		return isSuspended();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IStep#canStepOver()
	 */
	@Override
	public boolean canStepOver() {
		return isSuspended();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IStep#canStepReturn()
	 */
	@Override
	public boolean canStepReturn() {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IStep#isStepping()
	 */
	@Override
	public boolean isStepping() {
		return fStepping;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IStep#stepInto()
	 */
	@Override
	public synchronized void stepInto() throws DebugException {
		aboutToResume(DebugEvent.STEP_INTO, true);
		((AntDebugTarget) getDebugTarget()).stepInto();
	}

	private void aboutToResume(int detail, boolean stepping) {
		fRefreshProperties = true;
		fOldFrames = new ArrayList<>(fFrames);
		fFrames.clear();
		setPropertiesValid(false);
		setStepping(stepping);
		setBreakpoints(null);
		fireResumeEvent(detail);
	}

	private void setPropertiesValid(boolean valid) {
		if (fUserProperties != null) {
			fUserProperties.setValid(valid);
			fSystemProperties.setValid(valid);
			fRuntimeProperties.setValid(valid);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IStep#stepOver()
	 */
	@Override
	public synchronized void stepOver() throws DebugException {
		aboutToResume(DebugEvent.STEP_OVER, true);
		((AntDebugTarget) getDebugTarget()).stepOver();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.IStep#stepReturn()
	 */
	@Override
	public synchronized void stepReturn() throws DebugException {
		// do nothing
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
	 */
	@Override
	public boolean canTerminate() {
		return !isTerminated();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
	 */
	@Override
	public boolean isTerminated() {
		return getDebugTarget().isTerminated();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.debug.core.model.ITerminate#terminate()
	 */
	@Override
	public void terminate() throws DebugException {
		fFrames.clear();
		getDebugTarget().terminate();
	}

	/**
	 * Sets whether this thread is stepping
	 * 
	 * @param stepping
	 *            whether stepping
	 */
	protected void setStepping(boolean stepping) {
		fStepping = stepping;
	}

	public void buildStack(String data) {
		synchronized (fFrames) {
			String[] strings = data.split(DebugMessageIds.MESSAGE_DELIMITER);
			// 0 STACK message
			// 1 targetName
			// 2 taskName
			// 3 filePath
			// 4 lineNumber
			// 5 ...
			if (fOldFrames != null && (strings.length - 1) / 4 != fOldFrames.size()) {
				fOldFrames = null; // stack size changed..do not preserve
			}
			StringBuffer name;
			String filePath;
			int lineNumber;
			int stackFrameId = 0;
			String taskName;
			for (int i = 1; i < strings.length; i++) {
				if (strings[i].length() > 0) {
					name = new StringBuffer(strings[i]);
					taskName = strings[++i];
					if (taskName.length() > 0) {
						name.append(": "); //$NON-NLS-1$
						name.append(taskName);
					}
				} else {
					name = new StringBuffer(strings[++i]);
				}
				filePath = strings[++i];
				lineNumber = Integer.parseInt(strings[++i]);
				addFrame(stackFrameId++, name.toString(), filePath, lineNumber);
			}
			// wake up the call from getStackFrames
			fFrames.notifyAll();
		}
	}

	private void addFrame(int stackFrameId, String name, String filePath, int lineNumber) {
		AntStackFrame frame = getOldFrame();

		if (frame == null || !frame.getFilePath().equals(filePath)) {
			frame = new AntStackFrame(this, stackFrameId, name, filePath, lineNumber);
		} else {
			frame.setFilePath(filePath);
			frame.setId(stackFrameId);
			frame.setLineNumber(lineNumber);
			frame.setName(name);
		}
		fFrames.add(frame);
	}

	private AntStackFrame getOldFrame() {
		if (fOldFrames == null) {
			return null;
		}
		AntStackFrame frame = fOldFrames.remove(0);
		if (fOldFrames.isEmpty()) {
			fOldFrames = null;
		}
		return frame;
	}

	public void newProperties(String data) {
		synchronized (fPropertiesLock) {
			try {
				String[] datum = data.split(DebugMessageIds.MESSAGE_DELIMITER);
				if (fUserProperties == null) {
					initializePropertyGroups();
				}

				List<AntProperty> userProperties = ((AntPropertiesValue) fUserProperties.getLastValue()).getProperties();
				List<AntProperty> systemProperties = ((AntPropertiesValue) fSystemProperties.getLastValue()).getProperties();
				List<AntProperty> runtimeProperties = ((AntPropertiesValue) fRuntimeProperties.getLastValue()).getProperties();
				// 0 PROPERTIES message
				// 1 propertyName length
				// 2 propertyName
				// 3 propertyValue length
				// 3 propertyValue
				// 4 propertyType
				// 5 ...
				if (datum.length > 1) { // new properties
					StringBuffer propertyName;
					StringBuffer propertyValue;
					int propertyNameLength;
					int propertyValueLength;
					for (int i = 1; i < datum.length; i++) {
						propertyNameLength = Integer.parseInt(datum[i]);
						propertyName = new StringBuffer(datum[++i]);
						while (propertyName.length() != propertyNameLength) {
							propertyName.append(DebugMessageIds.MESSAGE_DELIMITER);
							propertyName.append(datum[++i]);
						}

						propertyName = getAntDebugTarget().getAntDebugController().unescapeString(propertyName);

						propertyValueLength = Integer.parseInt(datum[++i]);
						if (propertyValueLength == 0 && i + 1 == datum.length) { // bug 81299
							propertyValue = new StringBuffer(""); //$NON-NLS-1$
						} else {
							propertyValue = new StringBuffer(datum[++i]);
						}
						while (propertyValue.length() != propertyValueLength) {
							propertyValue.append(DebugMessageIds.MESSAGE_DELIMITER);
							propertyValue.append(datum[++i]);
						}

						propertyValue = getAntDebugTarget().getAntDebugController().unescapeString(propertyValue);

						int propertyType = Integer.parseInt(datum[++i]);
						addProperty(userProperties, systemProperties, runtimeProperties, propertyName.toString(), propertyValue.toString(), propertyType);
					}
				}
			}
			finally {
				fRefreshProperties = false;
				setPropertiesValid(true);
				// wake up the call from getVariables
				fPropertiesLock.notifyAll();
			}
		}
	}

	private void addProperty(List<AntProperty> userProperties, List<AntProperty> systemProperties, List<AntProperty> runtimeProperties, String propertyName, String propertyValue, int propertyType) {
		AntProperty property = new AntProperty((AntDebugTarget) getDebugTarget(), propertyName, propertyValue);
		switch (propertyType) {
			case DebugMessageIds.PROPERTY_SYSTEM:
				systemProperties.add(property);
				break;
			case DebugMessageIds.PROPERTY_USER:
				userProperties.add(property);
				break;
			case DebugMessageIds.PROPERTY_RUNTIME:
				runtimeProperties.add(property);
				break;
			default:
				break;
		}
	}

	private void initializePropertyGroups() {
		AntDebugTarget target = getAntDebugTarget();
		fUserProperties = new AntProperties(target, DebugModelMessages.AntThread_0);
		fUserProperties.setValue(new AntPropertiesValue(target));
		fSystemProperties = new AntProperties(target, DebugModelMessages.AntThread_1);
		fSystemProperties.setValue(new AntPropertiesValue(target));
		fRuntimeProperties = new AntProperties(target, DebugModelMessages.AntThread_2);
		fRuntimeProperties.setValue(new AntPropertiesValue(target));
	}

	protected IVariable[] getVariables() throws DebugException {
		synchronized (fPropertiesLock) {
			if (fRefreshProperties) {
				getAntDebugTarget().getProperties();
				if (fRefreshProperties) {
					// properties have not been set; need to wait
					try {
						int attempts = 0;
						while (fRefreshProperties && !isTerminated()) {
							fPropertiesLock.wait(50);
							if (attempts == 20 && fRefreshProperties && !isTerminated()) {
								throwDebugException(DebugModelMessages.AntThread_4);
							}
							attempts++;
						}
					}
					catch (InterruptedException ie) {
						// do nothing
					}
				}
			}
			if (fSystemProperties == null) {
				return new IVariable[0];
			}
			return new IVariable[] { fSystemProperties, fUserProperties, fRuntimeProperties };
		}
	}
}