/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.debugger.engine;

import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.*;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.breakpoints.Breakpoint;
import com.intellij.debugger.ui.impl.FrameVariablesTree;
import com.intellij.debugger.ui.impl.watch.*;
import com.intellij.debugger.ui.tree.render.ClassRenderer;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ColoredTextContainer;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
import com.intellij.xdebugger.frame.*;
import com.intellij.xdebugger.frame.presentation.XValuePresentation;
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
import com.intellij.xdebugger.settings.XDebuggerSettingsManager;
import com.sun.jdi.*;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.ExceptionEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author egor
 */
public class JavaStackFrame extends XStackFrame {
  private static final Logger LOG = Logger.getInstance(JavaStackFrame.class);

  private final DebugProcessImpl myDebugProcess;
  private final XSourcePosition myXSourcePosition;
  private final NodeManagerImpl myNodeManager;
  private final StackFrameDescriptorImpl myDescriptor;
  private static final JavaFramesListRenderer FRAME_RENDERER = new JavaFramesListRenderer();
  private JavaDebuggerEvaluator myEvaluator = null;

  public JavaStackFrame(@NotNull StackFrameProxyImpl stackFrameProxy,
                        @NotNull DebugProcessImpl debugProcess,
                        @NotNull MethodsTracker tracker,
                        @NotNull NodeManagerImpl nodeManager) {
    myDebugProcess = debugProcess;
    myNodeManager = nodeManager;
    myDescriptor = new StackFrameDescriptorImpl(stackFrameProxy, tracker);
    myDescriptor.setContext(null);
    myDescriptor.updateRepresentation(null, DescriptorLabelListener.DUMMY_LISTENER);
    myXSourcePosition = ApplicationManager.getApplication().runReadAction(new Computable<XSourcePosition>() {
      @Override
      public XSourcePosition compute() {
        return myDescriptor.getSourcePosition() != null ? DebuggerUtilsEx.toXSourcePosition(myDescriptor.getSourcePosition()) : null;
      }
    });
  }

  public StackFrameDescriptorImpl getDescriptor() {
    return myDescriptor;
  }

  @Nullable
  @Override
  public XDebuggerEvaluator getEvaluator() {
    if (myEvaluator == null) {
      myEvaluator = new JavaDebuggerEvaluator(myDebugProcess, this);
    }
    return myEvaluator;
  }

  @Nullable
  @Override
  public XSourcePosition getSourcePosition() {
    return myXSourcePosition;
  }

  @Override
  public void customizePresentation(@NotNull ColoredTextContainer component) {
    StackFrameDescriptorImpl selectedDescriptor = null;
    DebuggerSession session = myDebugProcess.getSession();
    if (session != null) {
      XDebugSession xSession = session.getXDebugSession();
      if (xSession != null) {
        XStackFrame frame = xSession.getCurrentStackFrame();
        if (frame instanceof JavaStackFrame) {
          selectedDescriptor = ((JavaStackFrame)frame).getDescriptor();
        }
      }
    }
    FRAME_RENDERER.customizePresentation(myDescriptor, component, selectedDescriptor);
  }

  @Override
  public void computeChildren(@NotNull final XCompositeNode node) {
    XStackFrame xFrame = getDescriptor().getXStackFrame();
    if (xFrame != null) {
      xFrame.computeChildren(node);
      return;
    }
    myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext()) {
      @Override
      public Priority getPriority() {
        return Priority.NORMAL;
      }

      @Override
      public void threadAction() {
        XValueChildrenList children = new XValueChildrenList();
        buildVariablesThreadAction(getFrameDebuggerContext(), children, node);
        node.addChildren(children, true);
      }
    });
  }

  DebuggerContextImpl getFrameDebuggerContext() {
    DebuggerManagerThreadImpl.assertIsManagerThread();
    DebuggerContextImpl context = myDebugProcess.getDebuggerContext();
    if (context.getFrameProxy() != getStackFrameProxy()) {
      SuspendContextImpl threadSuspendContext = SuspendManagerUtil.getSuspendContextForThread(context.getSuspendContext(), getStackFrameProxy().threadProxy());
      context = DebuggerContextImpl.createDebuggerContext(
        myDebugProcess.mySession,
        threadSuspendContext,
        getStackFrameProxy().threadProxy(),
        getStackFrameProxy());
      context.setPositionCache(myDescriptor.getSourcePosition());
      context.initCaches();
    }
    return context;
  }

  // copied from DebuggerTree
  private void buildVariablesThreadAction(DebuggerContextImpl debuggerContext, XValueChildrenList children, XCompositeNode node) {
    try {
      final StackFrameDescriptorImpl stackDescriptor = myDescriptor;
      final StackFrameProxyImpl frame = getStackFrameProxy();

      final EvaluationContextImpl evaluationContext = debuggerContext.createEvaluationContext();
      if (!debuggerContext.isEvaluationPossible()) {
        node.setErrorMessage(MessageDescriptor.EVALUATION_NOT_POSSIBLE.getLabel());
        //myChildren.add(myNodeManager.createNode(MessageDescriptor.EVALUATION_NOT_POSSIBLE, evaluationContext));
      }

      final Location location = frame.location();
      LOG.assertTrue(location != null);

      final ObjectReference thisObjectReference = frame.thisObject();
      if (thisObjectReference != null) {
        ValueDescriptorImpl thisDescriptor = myNodeManager.getThisDescriptor(stackDescriptor, thisObjectReference);
        children.add(JavaValue.create(thisDescriptor, evaluationContext, myNodeManager));
      }
      else {
        StaticDescriptorImpl staticDecriptor = myNodeManager.getStaticDescriptor(stackDescriptor, location.method().declaringType());
        if (staticDecriptor.isExpandable()) {
          children.addTopGroup(new JavaStaticGroup(staticDecriptor, evaluationContext, myNodeManager));
        }
      }

      DebugProcessImpl debugProcess = debuggerContext.getDebugProcess();
      if (debugProcess == null) {
        return;
      }

      // add last method return value if any
      final Pair<Method, Value> methodValuePair = debugProcess.getLastExecutedMethod();
      if (methodValuePair != null) {
        ValueDescriptorImpl returnValueDescriptor = myNodeManager.getMethodReturnValueDescriptor(stackDescriptor, methodValuePair.getFirst(), methodValuePair.getSecond());
        children.add(JavaValue.create(returnValueDescriptor, evaluationContext, myNodeManager));
      }
      // add context exceptions
      for (Pair<Breakpoint, Event> pair : DebuggerUtilsEx.getEventDescriptors(debuggerContext.getSuspendContext())) {
        final Event debugEvent = pair.getSecond();
        if (debugEvent instanceof ExceptionEvent) {
          final ObjectReference exception = ((ExceptionEvent)debugEvent).exception();
          if (exception != null) {
            final ValueDescriptorImpl exceptionDescriptor = myNodeManager.getThrownExceptionObjectDescriptor(stackDescriptor, exception);
            children.add(JavaValue.create(exceptionDescriptor, evaluationContext, myNodeManager));
          }
        }
      }

      final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer();
      if (classRenderer.SHOW_VAL_FIELDS_AS_LOCAL_VARIABLES) {
        if (thisObjectReference != null && debugProcess.getVirtualMachineProxy().canGetSyntheticAttribute())  {
          final ReferenceType thisRefType = thisObjectReference.referenceType();
          if (thisRefType instanceof ClassType && thisRefType.equals(location.declaringType()) && thisRefType.name().contains("$")) { // makes sense for nested classes only
            final ClassType clsType = (ClassType)thisRefType;
            final VirtualMachineProxyImpl vm = debugProcess.getVirtualMachineProxy();
            for (Field field : clsType.fields()) {
              if ((!vm.canGetSyntheticAttribute() || field.isSynthetic()) && StringUtil
                .startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) {
                final FieldDescriptorImpl fieldDescriptor = myNodeManager.getFieldDescriptor(stackDescriptor, thisObjectReference, field);
                children.add(JavaValue.create(fieldDescriptor, evaluationContext, myNodeManager));
              }
            }
          }
        }
      }

      try {
        buildVariables(debuggerContext, evaluationContext, children, node);
        //if (classRenderer.SORT_ASCENDING) {
        //  Collections.sort(myChildren, NodeManagerImpl.getNodeComparator());
        //}
      }
      catch (EvaluateException e) {
        node.setErrorMessage(e.getMessage());
        //myChildren.add(myNodeManager.createMessageNode(new MessageDescriptor(e.getMessage())));
      }
    }
    catch (EvaluateException e) {
      node.setErrorMessage(e.getMessage());
      //myChildren.clear();
      //myChildren.add(myNodeManager.createMessageNode(new MessageDescriptor(e.getMessage())));
    }
    catch (InvalidStackFrameException e) {
      LOG.info(e);
      //myChildren.clear();
      //notifyCancelled();
    }
    catch (InternalException e) {
      if (e.errorCode() == 35) {
        node.setErrorMessage(DebuggerBundle.message("error.corrupt.debug.info", e.getMessage()));
        //myChildren.add(
        //  myNodeManager.createMessageNode(new MessageDescriptor(DebuggerBundle.message("error.corrupt.debug.info", e.getMessage()))));
      }
      else {
        throw e;
      }
    }
  }

  // copied from FrameVariablesTree
  private void buildVariables(DebuggerContextImpl debuggerContext, EvaluationContextImpl evaluationContext, XValueChildrenList children, XCompositeNode node) throws EvaluateException {
    boolean myAutoWatchMode = DebuggerSettings.getInstance().AUTO_VARIABLES_MODE;
    if (evaluationContext == null) {
      return;
    }
    final SourcePosition sourcePosition = debuggerContext.getSourcePosition();
    if (sourcePosition == null) {
      return;
    }

    try {
      if (!XDebuggerSettingsManager.getInstance().getDataViewSettings().isAutoExpressions() && !myAutoWatchMode) {
        // optimization
        superBuildVariables(evaluationContext, children);
      }
      else {
        final Map<String, LocalVariableProxyImpl> visibleVariables = FrameVariablesTree.getVisibleVariables(getStackFrameProxy());
        final EvaluationContextImpl evalContext = evaluationContext;
        final Pair<Set<String>, Set<TextWithImports>> usedVars =
          ApplicationManager.getApplication().runReadAction(new Computable<Pair<Set<String>, Set<TextWithImports>>>() {
            @Override
            public Pair<Set<String>, Set<TextWithImports>> compute() {
              return FrameVariablesTree.findReferencedVars(visibleVariables.keySet(), sourcePosition, evalContext);
            }
          });
        // add locals
        if (myAutoWatchMode) {
          for (String var : usedVars.first) {
            final LocalVariableDescriptorImpl descriptor = myNodeManager.getLocalVariableDescriptor(null, visibleVariables.get(var));
            children.add(JavaValue.create(descriptor, evaluationContext, myNodeManager));
          }
        }
        else {
          superBuildVariables(evaluationContext, children);
        }
        // add expressions
        final EvaluationContextImpl evalContextCopy = evaluationContext.createEvaluationContext(evaluationContext.getThisObject());
        evalContextCopy.setAutoLoadClasses(false);
        for (TextWithImports text : usedVars.second) {
          WatchItemDescriptor descriptor = myNodeManager.getWatchItemDescriptor(null, text, null);
          children.add(JavaValue.create(descriptor, evaluationContext, myNodeManager));
        }
      }
    }
    catch (EvaluateException e) {
      if (e.getCause() instanceof AbsentInformationException) {
        final StackFrameProxyImpl frame = getStackFrameProxy();

        final Collection<Value> argValues = frame.getArgumentValues();
        int index = 0;
        for (Value argValue : argValues) {
          children.add(createArgumentValue(index++, argValue, null, evaluationContext));
        }
        //node.setMessage(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE.getLabel(), XDebuggerUIConstants.INFORMATION_MESSAGE_ICON, SimpleTextAttributes.REGULAR_ATTRIBUTES, null);
        children.add(new DummyMessageValueNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE.getLabel(), XDebuggerUIConstants.INFORMATION_MESSAGE_ICON));
        //myChildren.add(myNodeManager.createMessageNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE));

        // trying to collect values from variable slots
        final List<DecompiledLocalVariable> decompiled = FrameVariablesTree.collectVariablesFromBytecode(frame, argValues.size());
        if (!decompiled.isEmpty()) {
          try {
            final Map<DecompiledLocalVariable, Value> values = LocalVariablesUtil.fetchValues(frame.getStackFrame(), decompiled);
            for (DecompiledLocalVariable var : decompiled) {
              children.add(createArgumentValue(var.getSlot(), values.get(var), var.getName(), evaluationContext));
            }
          }
          catch (Exception ex) {
            LOG.info(ex);
          }
        }
      }
      else {
        throw e;
      }
    }
  }

  static class DummyMessageValueNode extends XNamedValue {
    private final String myMessage;
    private final Icon myIcon;

    public DummyMessageValueNode(String message, Icon icon) {
      super("");
      myMessage = message;
      myIcon = icon;
    }

    @Override
    public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
      node.setPresentation(myIcon, new XValuePresentation() {
        @NotNull
        @Override
        public String getSeparator() {
          return "";
        }

        @Override
        public void renderValue(@NotNull XValueTextRenderer renderer) {
          renderer.renderValue(myMessage);
        }
      }, false);
    }
  }

  private JavaValue createArgumentValue(int index, Value value, String name, EvaluationContextImpl evaluationContext) {
    ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, index, value, name);
    // setContext is required to calculate correct name
    descriptor.setContext(evaluationContext);
    return JavaValue.create(null, descriptor, evaluationContext, myNodeManager, true);
  }

  protected void superBuildVariables(final EvaluationContextImpl evaluationContext, XValueChildrenList children) throws EvaluateException {
    final StackFrameProxyImpl frame = getStackFrameProxy();
    for (final LocalVariableProxyImpl local : frame.visibleVariables()) {
      final LocalVariableDescriptorImpl descriptor = myNodeManager.getLocalVariableDescriptor(null, local);
      children.add(JavaValue.create(descriptor, evaluationContext, myNodeManager));
    }
  }

  public StackFrameProxyImpl getStackFrameProxy() {
    return myDescriptor.getFrameProxy();
  }

  @Nullable
  @Override
  public Object getEqualityObject() {
    return myDescriptor.getMethod();
  }
}
