/*
 * (c) Copyright QNX Software Systems Ltd. 2002.
 * All Rights Reserved.
 */
package org.eclipse.cdt.debug.mi.core;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.cdt.debug.mi.core.command.Command;
import org.eclipse.cdt.debug.mi.core.command.MIExecContinue;
import org.eclipse.cdt.debug.mi.core.command.MIExecFinish;
import org.eclipse.cdt.debug.mi.core.command.MIExecNext;
import org.eclipse.cdt.debug.mi.core.command.MIExecNextInstruction;
import org.eclipse.cdt.debug.mi.core.command.MIExecReturn;
import org.eclipse.cdt.debug.mi.core.command.MIExecStep;
import org.eclipse.cdt.debug.mi.core.command.MIExecStepInstruction;
import org.eclipse.cdt.debug.mi.core.command.MIExecUntil;
import org.eclipse.cdt.debug.mi.core.event.MIBreakpointHitEvent;
import org.eclipse.cdt.debug.mi.core.event.MIErrorEvent;
import org.eclipse.cdt.debug.mi.core.event.MIEvent;
import org.eclipse.cdt.debug.mi.core.event.MIFunctionFinishedEvent;
import org.eclipse.cdt.debug.mi.core.event.MIInferiorExitEvent;
import org.eclipse.cdt.debug.mi.core.event.MIInferiorSignalExitEvent;
import org.eclipse.cdt.debug.mi.core.event.MILocationReachedEvent;
import org.eclipse.cdt.debug.mi.core.event.MIRunningEvent;
import org.eclipse.cdt.debug.mi.core.event.MISharedLibEvent;
import org.eclipse.cdt.debug.mi.core.event.MISignalEvent;
import org.eclipse.cdt.debug.mi.core.event.MISteppingRangeEvent;
import org.eclipse.cdt.debug.mi.core.event.MIStoppedEvent;
import org.eclipse.cdt.debug.mi.core.event.MIWatchpointScopeEvent;
import org.eclipse.cdt.debug.mi.core.event.MIWatchpointTriggerEvent;
import org.eclipse.cdt.debug.mi.core.output.MIAsyncRecord;
import org.eclipse.cdt.debug.mi.core.output.MIConsoleStreamOutput;
import org.eclipse.cdt.debug.mi.core.output.MIConst;
import org.eclipse.cdt.debug.mi.core.output.MIExecAsyncOutput;
import org.eclipse.cdt.debug.mi.core.output.MILogStreamOutput;
import org.eclipse.cdt.debug.mi.core.output.MINotifyAsyncOutput;
import org.eclipse.cdt.debug.mi.core.output.MIOOBRecord;
import org.eclipse.cdt.debug.mi.core.output.MIOutput;
import org.eclipse.cdt.debug.mi.core.output.MIResult;
import org.eclipse.cdt.debug.mi.core.output.MIResultRecord;
import org.eclipse.cdt.debug.mi.core.output.MIStatusAsyncOutput;
import org.eclipse.cdt.debug.mi.core.output.MIStreamRecord;
import org.eclipse.cdt.debug.mi.core.output.MITargetStreamOutput;
import org.eclipse.cdt.debug.mi.core.output.MIValue;

/**
 * Receiving thread of gdb response output.
 */
public class RxThread extends Thread {

	final MISession session;
	List oobList;

	public RxThread(MISession s) {
		super("MI RX Thread");
		session = s;
		oobList = new ArrayList();
	}

	/*
	 * Get the response, parse the output, dispatch for OOB
	 * search for the corresponding token in rxQueue for the ResultRecord.
	 */
	public void run() {
		BufferedReader reader = new BufferedReader(new InputStreamReader(session.getChannelInputStream()));
		try {
			String line;
			while ((line = reader.readLine()) != null) {
				// TRACING: print the output.
				MIPlugin.getDefault().debugLog(line);
				processMIOutput(line + "\n");
			}
		} catch (IOException e) {
			//e.printStackTrace();
		}
		// This code should be executed when gdb been abruptly
		// or unxepectedly killed.  This is detected by checking
		// if the channelInputStream is not null.  In normal case
		// session.terminate() will set the channelInputStream to null.
		if (session.getChannelInputStream() != null) {
			Runnable cleanup = new Runnable() {
				public void run() {
					// Change the state of the inferior.
					session.getMIInferior().setTerminated();
					session.terminate();
				}
			};
			Thread clean = new Thread(cleanup, "GDB Died");
			clean.setDaemon(true);
			clean.start();
		}
		// Clear the queue and notify any command waiting, we are going down.
		CommandQueue rxQueue = session.getRxQueue();
		if (rxQueue != null) {
			Command[] cmds = rxQueue.clearCommands();
			for (int i = 0; i < cmds.length; i++) {
				synchronized (cmds[i]) {
					cmds[i].notifyAll();
				}
			}
		}
	}

	/**
	 * Search for the command in the RxQueue, set the MIOutput
	 * and notify() the other end.
	 * Any OOBs are consider like event and dipatch to the
	 * listeners/observers in different thread.
	 */
	void processMIOutput(String buffer) {
		MIOutput response = session.parse(buffer);
		if (response != null) {
			List list = new ArrayList();
			CommandQueue rxQueue = session.getRxQueue();

			// Notify any command waiting for a ResultRecord.
			MIResultRecord rr = response.getMIResultRecord();
			if (rr != null) {
				int id = rr.getToken();
				Command cmd = rxQueue.removeCommand(id);

				// Clear the accumulate oobList on each new Result Command
				// response.
				MIOOBRecord[] oobRecords = (MIOOBRecord[]) oobList.toArray(new MIOOBRecord[0]);
				oobList.clear();

				// Check if the state changed.
				String state = rr.getResultClass();
				if ("running".equals(state)) {
					int type = 0;
					// Check the type of command
					// if it was a step instruction set state stepping
					if (cmd instanceof MIExecNext) {
						type = MIRunningEvent.NEXT;
					} else if (cmd instanceof MIExecNextInstruction) {
						type = MIRunningEvent.NEXTI;
					} else if (cmd instanceof MIExecStep) {
						type = MIRunningEvent.STEP;
					} else if (cmd instanceof MIExecStepInstruction) {
						type = MIRunningEvent.STEPI;
					} else if (cmd instanceof MIExecUntil) {
						type = MIRunningEvent.UNTIL;
					} else if (cmd instanceof MIExecFinish) {
						type = MIRunningEvent.FINISH;
					} else if (cmd instanceof MIExecReturn) {
						type = MIRunningEvent.RETURN;
					} else if (cmd instanceof MIExecContinue) {
						type = MIRunningEvent.CONTINUE;
					} else {
						type = MIRunningEvent.CONTINUE;
					}
					session.getMIInferior().setRunning();
					MIEvent event = new MIRunningEvent(id, type);
					session.fireEvent(event);
				} else if ("exit".equals(state)) {
					// No need to do anything, terminate() will.
					session.getMIInferior().setTerminated();
				} else if ("connected".equals(state)) {
					session.getMIInferior().setConnected();
				} else if ("error".equals(state)) {
					if (session.getMIInferior().isRunning()) {
						session.getMIInferior().setSuspended();
						MIEvent event = new MIErrorEvent(rr, oobRecords);
						session.fireEvent(event);
					}
				}

				// Notify the waiting command.
				if (cmd != null) {
					synchronized (cmd) {
						// Set the accumulate console Stream
						response.setMIOOBRecords(oobRecords);
						cmd.setMIOutput(response);
						cmd.notifyAll();
					}
				}
				// Some result record contains informaton specific to oob.
				// This will happen when CLI-Command is use, for example
				// doing "run" will block and return a breakpointhit
				processMIOOBRecord(rr, list);

			} else {

				// Process OOBs
				MIOOBRecord[] oobs = response.getMIOOBRecords();
				for (int i = 0; i < oobs.length; i++) {
					processMIOOBRecord(oobs[i], list);
				}
			}

			MIEvent[] events = (MIEvent[]) list.toArray(new MIEvent[list.size()]);
			session.fireEvents(events);
		} // if response != null
	}

	/**
	 * Dispatch a thread to deal with the listeners.
	 */
	void processMIOOBRecord(MIOOBRecord oob, List list) {
		if (oob instanceof MIAsyncRecord) {
			processMIOOBRecord((MIAsyncRecord) oob, list);
			oobList.clear();
		} else if (oob instanceof MIStreamRecord) {
			processMIOOBRecord((MIStreamRecord) oob);
		}
	}

	void processMIOOBRecord(MIAsyncRecord async, List list) {
		if (async instanceof MIExecAsyncOutput) {
			MIExecAsyncOutput exec = (MIExecAsyncOutput) async;
			// Change of state.
			String state = exec.getAsyncClass();
			if ("stopped".equals(state)) {
				MIEvent e = null;
				MIResult[] results = exec.getMIResults();
				for (int i = 0; i < results.length; i++) {
					String var = results[i].getVariable();
					MIValue val = results[i].getMIValue();
					if (var.equals("reason")) {
						if (val instanceof MIConst) {
							String reason = ((MIConst) val).getString();
							e = createEvent(reason, exec);
							if (e != null) {
								list.add(e);
							}
						}
					}
				}

				// GDB does not have reason when stopping on shared, hopefully
				// this will be fix in newer version meanwhile, we will use a hack
				// to cope.  On most platform we can detect by looking at the
				// console stream for phrase:
				// 	~"Stopped due to shared library event\n"
				//
				// Althought it is a _real_ bad idea to do this, we do not have
				// any other alternatives.
				String[] logs = getStreamRecords();
				for (int i = 0; i < logs.length; i++) {
					if (logs[i].equalsIgnoreCase("Stopped due to shared library event")) {
						session.getMIInferior().setSuspended();
						e = new MISharedLibEvent(exec);
						list.add(e);
					}
				}

				// We were stopped for some unknown reason, for example
				// GDB for temporary breakpoints will not send the
				// "reason" ??? still fire a stopped event.
				if (e == null) {
					session.getMIInferior().setSuspended();
					e = new MIStoppedEvent(exec);
					list.add(e);
				}
			}
		} else if (async instanceof MIStatusAsyncOutput) {
			// Nothing done .. but what about +download??
		} else if (async instanceof MINotifyAsyncOutput) {
			// Nothing
		}
	}

	void processMIOOBRecord(MIStreamRecord stream) {
		if (stream instanceof MIConsoleStreamOutput) {
			OutputStream console = session.getConsolePipe();
			if (console != null) {
				MIConsoleStreamOutput out = (MIConsoleStreamOutput) stream;
				String str = out.getString();
				if (str != null) {
					try {
						console.write(str.getBytes());
						console.flush();
					} catch (IOException e) {
					}
				}
			}
			// Accumulate the Console Stream Output response for parsing.
			// Some commands will put valuable info  in the Console Stream.
			oobList.add(stream);
		} else if (stream instanceof MITargetStreamOutput) {
			OutputStream target = session.getMIInferior().getPipedOutputStream();
			if (target != null) {
				MITargetStreamOutput out = (MITargetStreamOutput) stream;
				String str = out.getString();
				if (str != null) {
					try {
						target.write(str.getBytes());
						target.flush();
					} catch (IOException e) {
					}
				}
			}
		} else if (stream instanceof MILogStreamOutput) {
			// This is meant for the gdb console.
			OutputStream log = session.getLogPipe();
			if (log != null) {
				MILogStreamOutput out = (MILogStreamOutput) stream;
				String str = out.getString();
				if (str != null) {
					try {
						log.write(str.getBytes());
						log.flush();
					} catch (IOException e) {
					}
				}
			}
			// Accumulate the Log Stream Output response for parsing.
			// Some commands will put valuable info  in the Log Stream.
			oobList.add(stream);
		}
	}

	/**
	 * Dispatch a thread to deal with the listeners.
	 */
	void processMIOOBRecord(MIResultRecord rr, List list) {
		MIResult[] results = rr.getMIResults();
		for (int i = 0; i < results.length; i++) {
			String var = results[i].getVariable();
			if (var.equals("reason")) {
				MIValue value = results[i].getMIValue();
				if (value instanceof MIConst) {
					String reason = ((MIConst) value).getString();
					MIEvent event = createEvent(reason, rr);
					if (event != null) {
						list.add(event);
					}
				}
			}
		}
	}

	MIEvent createEvent(String reason, MIExecAsyncOutput exec) {
		return createEvent(reason, null, exec);
	}

	MIEvent createEvent(String reason, MIResultRecord rr) {
		return createEvent(reason, rr, null);
	}

	MIEvent createEvent(String reason, MIResultRecord rr, MIExecAsyncOutput exec) {
		MIEvent event = null;
		if ("breakpoint-hit".equals(reason)) {
			if (exec != null) {
				event = new MIBreakpointHitEvent(exec);
			} else if (rr != null) {
				event = new MIBreakpointHitEvent(rr);
			}
			session.getMIInferior().setSuspended();
		} else if (
			"watchpoint-trigger".equals(reason)
				|| "read-watchpoint-trigger".equals(reason)
				|| "access-watchpoint-trigger".equals(reason)) {
			if (exec != null) {
				event = new MIWatchpointTriggerEvent(exec);
			} else if (rr != null) {
				event = new MIWatchpointTriggerEvent(rr);
			}
			session.getMIInferior().setSuspended();
		} else if ("watchpoint-scope".equals(reason)) {
			if (exec != null) {
				event = new MIWatchpointScopeEvent(exec);
			} else if (rr != null) {
				event = new MIWatchpointScopeEvent(rr);
			}
			session.getMIInferior().setSuspended();
		} else if ("end-stepping-range".equals(reason)) {
			if (exec != null) {
				event = new MISteppingRangeEvent(exec);
			} else if (rr != null) {
				event = new MISteppingRangeEvent(rr);
			}
			session.getMIInferior().setSuspended();
		} else if ("signal-received".equals(reason)) {
			if (exec != null) {
				event = new MISignalEvent(exec);
			} else if (rr != null) {
				event = new MISignalEvent(rr);
			}
			session.getMIInferior().setSuspended();
		} else if ("location-reached".equals(reason)) {
			if (exec != null) {
				event = new MILocationReachedEvent(exec);
			} else if (rr != null) {
				event = new MILocationReachedEvent(rr);
			}
			session.getMIInferior().setSuspended();
		} else if ("function-finished".equals(reason)) {
			if (exec != null) {
				event = new MIFunctionFinishedEvent(exec);
			} else if (rr != null) {
				event = new MIFunctionFinishedEvent(rr);
			}
			session.getMIInferior().setSuspended();
		} else if ("exited-normally".equals(reason) || "exited".equals(reason)) {
			if (exec != null) {
				event = new MIInferiorExitEvent(exec);
			} else if (rr != null) {
				event = new MIInferiorExitEvent(rr);
			}
			session.getMIInferior().setTerminated();
		} else if ("exited-signalled".equals(reason)) {
			if (exec != null) {
				event = new MIInferiorSignalExitEvent(exec);
			} else if (rr != null) {
				event = new MIInferiorSignalExitEvent(rr);
			}
			session.getMIInferior().setTerminated();
		}
		return event;
	}

	String[] getStreamRecords() {
		List streamRecords = new ArrayList();
		MIOOBRecord[] oobRecords = (MIOOBRecord[]) oobList.toArray(new MIOOBRecord[0]);
		for (int i = 0; i < oobRecords.length; i++) {
			if (oobRecords[i] instanceof MIStreamRecord) {
				String s = ((MIStreamRecord) oobRecords[i]).getString().trim();
				if (s != null && s.length() > 0) {
					streamRecords.add(s);
				}
			}
		}
		return (String[]) streamRecords.toArray(new String[0]);
	}

}
