package com.gsamokovarov.bindex;

import java.lang.reflect.Field;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Frame;
import org.jruby.runtime.backtrace.BacktraceElement;
import org.jruby.runtime.builtin.IRubyObject;

/**
 * Breaks <code>ThreadContext</code> encapsulation.
 *
 * The following private fields of <code>ThreadContext</code> are accessible
 * through an instance of this class:
 *
 * <ul>
 *   <li>frameStack</li>
 *   <li>frameIndex</li>
 *   <li>scopeStack</li>
 *   <li>scopeIndex</li>
 *   <li>backtrace</li>
 *   <li>backtraceIndex</li>
 * </ul>
 */
public class ThreadContextInternals {
  private ThreadContext context;

  public ThreadContextInternals(ThreadContext context) {
    this.context = context;
  }

  public Frame[] getFrameStack() {
    return (Frame[]) getPrivateField(context, "frameStack");
  }

  public int getFrameIndex() {
    return (Integer) getPrivateField(context, "frameIndex");
  }

  public DynamicScope[] getScopeStack() {
    return (DynamicScope[]) getPrivateField(context, "scopeStack");
  }

  public int getScopeIndex() {
    return (Integer) getPrivateField(context, "scopeIndex");
  }

  public BacktraceElement[] getBacktrace() {
    return (BacktraceElement[]) getPrivateField(context, "backtrace");
  }

  public int getBacktraceIndex() {
    return (Integer) getPrivateField(context, "backtraceIndex");
  }

  private Object getPrivateField(ThreadContext context, String fieldName) {
    try {
      Field field = ThreadContext.class.getDeclaredField(fieldName);

      field.setAccessible(true);

      return field.get(context);
    } catch (NoSuchFieldException exc) {
      throw new ThreadContextInterfaceException(fieldName, exc);
    } catch (IllegalAccessException exc) {
      throw new ThreadContextInterfaceException(fieldName, exc);
    }
  }
}

@@ -851,33 +851,24 @@
 rivateField(
-context, 
 %22frameStack%22
@@ -943,25 +943,16 @@
 teField(
-context, 
 %22frameIn
@@ -1045,33 +1045,24 @@
 rivateField(
-context, 
 %22scopeStack%22
@@ -1137,25 +1137,16 @@
 teField(
-context, 
 %22scopeIn
@@ -1246,33 +1246,24 @@
 rivateField(
-context, 
 %22backtrace%22)
@@ -1341,25 +1341,16 @@
 teField(
-context, 
 %22backtra
@@ -1402,31 +1402,8 @@
 eld(
-ThreadContext context, 
 Stri

Use the private field context for cleaner getPrivateField API