/*
   * (non-Javadoc)
   *
   * @see org.eclipse.e4.languages.javascript.jsdi.ThreadReference#frames()
   */
  public synchronized List frames() {
    if (!suspended || status == THREAD_STATUS_ZOMBIE) return Collections.EMPTY_LIST;

    if (frames != null) return frames;

    Request request = new Request(JSONConstants.FRAMES);
    request.getArguments().put(JSONConstants.THREAD_ID, threadId);
    try {
      Response response = vm.sendRequest(request, 30000);
      List frameIds = (List) response.getBody().get(JSONConstants.FRAMES);
      if (frameIds.isEmpty()) {
        frames = Collections.EMPTY_LIST;
        return frames;
      }
      frames = new ArrayList();
      for (Iterator iterator = frameIds.iterator(); iterator.hasNext(); ) {
        Long frameId = new Long(((Number) iterator.next()).longValue());
        StackFrameReferenceImpl frame = createStackFrame(frameId);
        frames.add(frame);
      }
    } catch (DisconnectException e) {
      e.printStackTrace();
    } catch (TimeoutException e) {
      e.printStackTrace();
    }
    return frames;
  }
 /*
  * (non-Javadoc)
  *
  * @see org.eclipse.e4.languages.javascript.jsdi.ThreadReference#suspend()
  */
 public void suspend() {
   if (status == THREAD_STATUS_ZOMBIE) {
     return;
   }
   Request request = new Request(JSONConstants.SUSPEND);
   request.getArguments().put(JSONConstants.THREAD_ID, threadId);
   try {
     vm.sendRequest(request, 30000);
   } catch (DisconnectException e) {
     e.printStackTrace();
   } catch (TimeoutException e) {
     e.printStackTrace();
   }
 }
 /**
  * Sends a request to make a new {@link StackFrameReference} in the current debugger. Returns a
  * new {@link StackFrameReference} on success, <code>null</code> on failure
  *
  * @param frameId
  * @return a new {@link StackFrameReference} or <code>null</code>
  */
 private StackFrameReferenceImpl createStackFrame(Long frameId) {
   Request request = new Request(JSONConstants.FRAME);
   request.getArguments().put(JSONConstants.THREAD_ID, threadId);
   request.getArguments().put(JSONConstants.FRAME_ID, frameId);
   try {
     Response response = vm.sendRequest(request, 30000);
     Map jsonFrame = (Map) response.getBody().get(JSONConstants.FRAME);
     return new StackFrameReferenceImpl(vm, jsonFrame);
   } catch (DisconnectException e) {
     e.printStackTrace();
   } catch (TimeoutException e) {
     e.printStackTrace();
   }
   return null;
 }
 /*
  * (non-Javadoc)
  *
  * @see org.eclipse.e4.languages.javascript.jsdi.ThreadReference#resume()
  */
 public synchronized void resume() {
   if (status == THREAD_STATUS_ZOMBIE) {
     return;
   }
   Request request = new Request(JSONConstants.CONTINUE);
   request.getArguments().put(JSONConstants.THREAD_ID, threadId);
   if (step != null) {
     request.getArguments().put(JSONConstants.STEP, step);
   }
   try {
     Response response = vm.sendRequest(request, 30000);
     if (response.isSuccess()) {
       step = null;
       frames = null;
       suspended = false;
       atBreakpoint = false;
     }
   } catch (DisconnectException e) {
     e.printStackTrace();
   } catch (TimeoutException e) {
     e.printStackTrace();
   }
 }
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.e4.languages.javascript.jsdi.event.EventQueue#remove(int)
   */
  public EventSet remove(int timeout) {
    try {
      while (true) {
        EventPacket event = vm.receiveEvent(timeout);
        String eventName = event.getEvent();
        EventSetImpl eventSet = new EventSetImpl(vm);
        if (eventName.equals(JSONConstants.SCRIPT)) {
          Long threadId =
              new Long(((Number) event.getBody().get(JSONConstants.THREAD_ID)).longValue());
          ThreadReferenceImpl thread = vm.getThread(threadId);
          eventSet.setThread(thread);

          Long scriptId =
              new Long(((Number) event.getBody().get(JSONConstants.SCRIPT_ID)).longValue());
          ScriptReferenceImpl script = vm.addScript(scriptId);

          List scriptLoadRequests = eventRequestManager.scriptLoadRequests();
          for (Iterator iterator = scriptLoadRequests.iterator(); iterator.hasNext(); ) {
            ScriptLoadRequest request = (ScriptLoadRequest) iterator.next();
            if (request.isEnabled())
              eventSet.add(new ScriptLoadEventImpl(vm, thread, script, request));
          }
        } else if (eventName.equals(JSONConstants.BREAK)) {
          Long threadId =
              new Long(((Number) event.getBody().get(JSONConstants.THREAD_ID)).longValue());
          ThreadReferenceImpl thread = vm.getThread(threadId);
          eventSet.setThread(thread);

          Long scriptId =
              new Long(((Number) event.getBody().get(JSONConstants.SCRIPT_ID)).longValue());
          ScriptReferenceImpl script = vm.getScript(scriptId);

          int lineNumber = ((Number) event.getBody().get(JSONConstants.LINE_NUMBER)).intValue();
          Location location = script.lineLocation(lineNumber);

          boolean atBreakpoint = false;

          List jsonBreakpoints = (List) event.getBody().get(JSONConstants.BREAKPOINTS);
          if (jsonBreakpoints != null) {
            List breakpoints = new ArrayList(jsonBreakpoints.size());
            for (Iterator iterator = jsonBreakpoints.iterator(); iterator.hasNext(); ) {
              Number breakpointId = (Number) iterator.next();
              breakpoints.add(new Long(breakpointId.longValue()));
            }

            List breakpointRequests = eventRequestManager.breakpointRequests();
            for (Iterator iterator = breakpointRequests.iterator(); iterator.hasNext(); ) {
              BreakpointRequestImpl request = (BreakpointRequestImpl) iterator.next();
              ThreadReference requestThread = request.thread();
              if (request.isEnabled()
                  && (requestThread == null || thread == requestThread)
                  && breakpoints.contains(request.breakpointId())) {
                eventSet.add(new BreakpointEventImpl(vm, thread, location, request));
                atBreakpoint = true;
              }
            }
          }

          String stepType = (String) event.getBody().get(JSONConstants.STEP);
          if (JSONConstants.SUSPENDED.equals(stepType)) {
            List suspendRequests = eventRequestManager.suspendRequests();
            for (Iterator iterator = suspendRequests.iterator(); iterator.hasNext(); ) {
              SuspendRequestImpl request = (SuspendRequestImpl) iterator.next();
              ThreadReference requestThread = request.thread();
              if (request.isEnabled() && (requestThread == null || thread == requestThread)) {
                eventSet.add(new SuspendEventImpl(vm, thread, location, request));
              }
            }
          } else if (stepType != null) {
            List stepRequests = eventRequestManager.stepRequests();
            for (Iterator iterator = stepRequests.iterator(); iterator.hasNext(); ) {
              StepRequestImpl request = (StepRequestImpl) iterator.next();
              ThreadReference requestThread = request.thread();
              if (request.isEnabled() && (requestThread == null || thread == requestThread)) {
                eventSet.add(new StepEventImpl(vm, thread, location, request));
              }
            }
          }

          Boolean debuggerStatement =
              (Boolean) event.getBody().get(JSONConstants.DEBUGGER_STATEMENT);
          if (debuggerStatement.booleanValue()) {
            List debuggerStatementRequests = eventRequestManager.debuggerStatementRequests();
            for (Iterator iterator = debuggerStatementRequests.iterator(); iterator.hasNext(); ) {
              DebuggerStatementRequestImpl request = (DebuggerStatementRequestImpl) iterator.next();
              ThreadReference requestThread = request.thread();
              if (request.isEnabled() && (requestThread == null || thread == requestThread)) {
                eventSet.add(new DebuggerStatementEventImpl(vm, thread, location, request));
              }
            }
          }

          if (!eventSet.isEmpty()) thread.markSuspended(atBreakpoint);
        } else if (eventName.equals(JSONConstants.EXCEPTION)) {
          Long threadId =
              new Long(((Number) event.getBody().get(JSONConstants.THREAD_ID)).longValue());
          ThreadReferenceImpl thread = vm.getThread(threadId);
          eventSet.setThread(thread);

          Long scriptId =
              new Long(((Number) event.getBody().get(JSONConstants.SCRIPT_ID)).longValue());
          ScriptReferenceImpl script = vm.getScript(scriptId);

          int lineNumber = ((Number) event.getBody().get(JSONConstants.LINE_NUMBER)).intValue();
          Location location = script.lineLocation(lineNumber);

          String message = (String) event.getBody().get(JSONConstants.MESSAGE);

          List exceptionRequests = eventRequestManager.exceptionRequests();
          for (Iterator iterator = exceptionRequests.iterator(); iterator.hasNext(); ) {
            ExceptionRequest request = (ExceptionRequest) iterator.next();
            if (request.isEnabled()) {
              eventSet.add(new ExceptionEventImpl(vm, thread, location, message, request));
            }
          }
          if (!eventSet.isEmpty()) thread.markSuspended(false);
        } else if (eventName.equals(JSONConstants.THREAD)) {
          Long threadId =
              new Long(((Number) event.getBody().get(JSONConstants.THREAD_ID)).longValue());

          String type = (String) event.getBody().get(JSONConstants.TYPE);

          if (JSONConstants.ENTER.equals(type)) {
            ThreadReferenceImpl thread = vm.addThread(threadId);
            eventSet.setThread(thread);
            List threadEnterRequests = eventRequestManager.threadEnterRequests();
            for (Iterator iterator = threadEnterRequests.iterator(); iterator.hasNext(); ) {
              ThreadEnterRequest request = (ThreadEnterRequest) iterator.next();
              if (request.isEnabled()) eventSet.add(new ThreadEnterEventImpl(vm, thread, request));
            }
          } else if (JSONConstants.EXIT.equals(type)) {
            ThreadReferenceImpl thread = vm.removeThread(threadId);
            List threadExitRequests = eventRequestManager.threadExitRequests();
            for (Iterator iterator = threadExitRequests.iterator(); iterator.hasNext(); ) {
              ThreadExitRequest request = (ThreadExitRequest) iterator.next();
              if (request.isEnabled()) eventSet.add(new ThreadExitEventImpl(vm, thread, request));
            }
          }
        }
        if (eventSet.isEmpty()) {
          eventSet.resume();
          continue;
        }
        return eventSet;
      }
    } catch (TimeoutException e) {
      e.printStackTrace();
    } catch (DisconnectException e) {
      vm.disconnectVM();
    }
    return null;
  }