package jetbrains.mps.debugger.java.runtime.ui.evaluation;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import javax.swing.JPanel;
import jetbrains.mps.logging.Logger;
import com.intellij.openapi.actionSystem.DataKey;
import jetbrains.mps.debugger.java.runtime.evaluation.container.IEvaluationContainer;
import jetbrains.mps.debugger.java.runtime.state.DebugSession;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.debug.api.SessionChangeAdapter;
import java.awt.BorderLayout;
import com.sun.jdi.ThreadReference;
import jetbrains.mps.debugger.java.api.evaluation.Evaluator;
import jetbrains.mps.debugger.java.api.evaluation.proxies.IValueProxy;
import jetbrains.mps.debugger.java.api.state.proxy.JavaValue;
import jetbrains.mps.debugger.java.api.state.customViewers.CustomViewersManager;
import jetbrains.mps.debugger.java.api.evaluation.EvaluationException;
import jetbrains.mps.debug.api.AbstractDebugSession;
import jetbrains.mps.debugger.java.runtime.state.JavaUiStateImpl;
import com.intellij.openapi.application.ApplicationManager;
import jetbrains.mps.debugger.java.api.state.proxy.JavaThread;
import jetbrains.mps.debugger.java.api.state.proxy.JavaLocation;
import jetbrains.mps.debugger.java.api.state.proxy.JavaStackFrame;

@GeneratedClass(node = "r:b4456070-b665-4c03-b3d3-15a7362ba923(jetbrains.mps.debugger.java.runtime.ui.evaluation)/7406771907178600108", model = "r:b4456070-b665-4c03-b3d3-15a7362ba923(jetbrains.mps.debugger.java.runtime.ui.evaluation)")
public abstract class EvaluationUi extends JPanel {
  private static final Logger LOG = Logger.getLogger(EvaluationUi.class);
  public static final DataKey<IEvaluationContainer> EVALUATION_CONTAINER = DataKey.create("Evaluation Container");
  public static final DataKey<DebugSession> DEBUG_SESSION = DataKey.create("Debug Session");
  @NotNull
  protected final DebugSession myDebugSession;
  protected final EvaluationTree myTree;
  private IErrorTextListener myErrorListener;
  private final boolean myAutoUpdate;
  private final SessionChangeAdapter mySessionChangeAdapter = new MySessionChangeAdapter();
  public EvaluationUi(@NotNull DebugSession session, boolean autoUpdate) {
    super(new BorderLayout());
    myDebugSession = session;
    myAutoUpdate = autoUpdate;
    myDebugSession.addChangeListener(mySessionChangeAdapter);
    myTree = new EvaluationTree(myDebugSession);
  }
  protected abstract void update();
  public abstract void evaluate();
  public void dispose() {
    myDebugSession.removeChangeListener(mySessionChangeAdapter);
    myTree.dispose();
  }
  protected void evaluate(final IEvaluationContainer model) {
    if (!(myDebugSession.getEvaluationProvider().canEvaluate())) {
      setErrorText("Program should be paused on breakpoint to evaluate");
      return;
    }
    new Thread("Debugger Evaluation thread") {
      @Override
      public void run() {
        try {
          final Class clazz = model.generateClass();
          setEvaluating(model);
          final ThreadReference thread = check_4q63yg_a0c0a0a0a0a1a21(myDebugSession.getUiState().getThread());
          myDebugSession.getEventsProcessor().scheduleEvaluation(() -> {
            try {
              Evaluator evaluator = model.createEvaluatorInstance(clazz);
              IValueProxy evaluatedValue = evaluator.evaluate();
              if (evaluatedValue != null) {
                JavaValue value = CustomViewersManager.getInstance().fromJdi(evaluatedValue.getJDIValue(), thread);
                value.initSubvalues();
                setSuccess(value, model);
              } else {
                setFailure("Evaluation returned null.", model);
              }
            } catch (EvaluationException e) {
              setFailure(e, model);
            } catch (Throwable t) {
              setFailure(t, model);
              LOG.error("Debug evaluation failed", t);
            }
          }, thread);
        } catch (EvaluationException e) {
          setFailure(e, model);
        } catch (Throwable t) {
          setFailure(t, model);
          LOG.error("Debug evaluation failed", t);
        }
      }
    }.start();
  }
  private void setSuccess(@NotNull final JavaValue evaluatedValue, final IEvaluationContainer model) {
    myTree.setResultValue(evaluatedValue, model);
    myTree.rebuildLater();
  }
  private void setEvaluating(final IEvaluationContainer model) {
    myTree.setEvaluating(model);
    myTree.rebuildLater();
  }

  private void setFailure(@NotNull final Throwable error, final IEvaluationContainer model) {
    myTree.setError(error, model);
    myTree.rebuildLater();
  }
  private void setFailure(@NotNull final String message, final IEvaluationContainer model) {
    myTree.setError(message, model);
    myTree.rebuildLater();
  }
  protected void setErrorText(String text) {
    if (myErrorListener != null) {
      myErrorListener.updateErrorText(text);
    }
  }
  public void setErrorTextListener(IErrorTextListener listener) {
    myErrorListener = listener;
  }
  public interface IErrorTextListener {
    void updateErrorText(String text);
  }
  private class MySessionChangeAdapter extends SessionChangeAdapter {
    public MySessionChangeAdapter() {
    }
    @Override
    public void paused(AbstractDebugSession session) {
      if (myDebugSession == session) {
        JavaUiStateImpl uiState = myDebugSession.getUiState();
        String unitName = check_4q63yg_a0b0a0b12(check_4q63yg_a0a1a0a1v(uiState.getStackFrame()));
        if ((unitName != null && unitName.length() > 0)) {
          myTree.updateLocation(uiState.getThread().getThread());
        }
        ApplicationManager.getApplication().invokeLater(new Runnable() {
          @Override
          public void run() {
            setErrorText("");
            update();
            if (myAutoUpdate) {
              evaluate();
            }
          }
        });
      }
    }
    @Override
    public void stateChanged(AbstractDebugSession session) {
      if (myDebugSession == session) {
        ApplicationManager.getApplication().invokeLater(new Runnable() {
          @Override
          public void run() {
            update();
          }
        });
      }
    }
    @Override
    public void resumed(AbstractDebugSession session) {
      if (myDebugSession == session) {
        myTree.rebuildLater();
      }
    }
  }
  private static ThreadReference check_4q63yg_a0c0a0a0a0a1a21(JavaThread checkedDotOperand) {
    if (null != checkedDotOperand) {
      return checkedDotOperand.getThread();
    }
    return null;
  }
  private static String check_4q63yg_a0b0a0b12(JavaLocation checkedDotOperand) {
    if (null != checkedDotOperand) {
      return checkedDotOperand.getUnitName();
    }
    return null;
  }
  private static JavaLocation check_4q63yg_a0a1a0a1v(JavaStackFrame checkedDotOperand) {
    if (null != checkedDotOperand) {
      return checkedDotOperand.getLocation();
    }
    return null;
  }
}
