/*
 * Copyright 2000-2009 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.ui.impl.watch;

import com.intellij.debugger.engine.StackFrameContext;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.jdi.LocalVariableProxy;
import com.intellij.debugger.engine.jdi.StackFrameProxy;
import com.intellij.debugger.engine.jdi.ThreadReferenceProxy;
import com.intellij.debugger.impl.descriptors.data.*;
import com.intellij.debugger.jdi.LocalVariableProxyImpl;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.jdi.ThreadGroupReferenceProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.ui.tree.NodeDescriptor;
import com.intellij.debugger.ui.tree.NodeDescriptorFactory;
import com.intellij.debugger.ui.tree.UserExpressionDescriptor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.sun.jdi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;

public class NodeDescriptorFactoryImpl implements NodeDescriptorFactory {
  private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.impl.watch.NodeDescriptorFactoryImpl");
  private DescriptorTree myCurrentHistoryTree = new DescriptorTree(true);

  private DescriptorTreeSearcher myDescriptorSearcher;
  private DescriptorTreeSearcher myDisplayDescriptorSearcher;

  protected final Project      myProject;

  public NodeDescriptorFactoryImpl(Project project) {
    myProject = project;
    myDescriptorSearcher = new DescriptorTreeSearcher(new MarkedDescriptorTree());
    myDisplayDescriptorSearcher = new DisplayDescriptorTreeSearcher(new MarkedDescriptorTree());
  }

  public void dispose() {
    myCurrentHistoryTree.clear();
    myDescriptorSearcher.clear();
    myDisplayDescriptorSearcher.clear();
  }

  public <T extends NodeDescriptor> T getDescriptor(NodeDescriptor parent, DescriptorData<T> key) {
    final T descriptor = key.createDescriptor(myProject);

    final T oldDescriptor = findDescriptor(parent, descriptor, key);

    if(oldDescriptor != null && oldDescriptor.getClass() == descriptor.getClass()) {
      descriptor.setAncestor(oldDescriptor);
    }
    else {
      T displayDescriptor = findDisplayDescriptor(parent, descriptor, key.getDisplayKey());
      if(displayDescriptor != null) {
        descriptor.displayAs(displayDescriptor);
      }
    }

    myCurrentHistoryTree.addChild(parent, descriptor);

    return descriptor;
  }

  @Nullable
  protected <T extends NodeDescriptor>T findDisplayDescriptor(NodeDescriptor parent, T descriptor, DisplayKey<T> key) {
    return myDisplayDescriptorSearcher.search(parent, descriptor, key);
  }

  @Nullable
  protected <T extends NodeDescriptor> T findDescriptor(NodeDescriptor parent, T descriptor, DescriptorData<T> key) {
    return myDescriptorSearcher.search(parent, descriptor, key);
  }

  public DescriptorTree getCurrentHistoryTree() {
    return myCurrentHistoryTree;
  }

  public void deriveHistoryTree(DescriptorTree tree, final StackFrameContext context) {
    deriveHistoryTree(tree, context.getFrameProxy());
  }

  public void deriveHistoryTree(DescriptorTree tree, final StackFrameProxy frameProxy) {

    final MarkedDescriptorTree descriptorTree = new MarkedDescriptorTree();
    final MarkedDescriptorTree displayDescriptorTree = new MarkedDescriptorTree();

    tree.dfst(new DescriptorTree.DFSTWalker() {
      @Override
      public void visit(NodeDescriptor parent, NodeDescriptor child) {
        final DescriptorData<NodeDescriptor> descriptorData = DescriptorData.getDescriptorData(child);
        descriptorTree.addChild(parent, child, descriptorData);
        displayDescriptorTree.addChild(parent, child, descriptorData.getDisplayKey());
      }
    });

    myDescriptorSearcher = new DescriptorTreeSearcher(descriptorTree);
    myDisplayDescriptorSearcher = new DisplayDescriptorTreeSearcher(displayDescriptorTree);

    myCurrentHistoryTree = createDescriptorTree(frameProxy, tree);
  }

  private static DescriptorTree createDescriptorTree(final StackFrameProxy frameProxy, final DescriptorTree fromTree) {
    int frameCount = -1;
    int frameIndex = -1;
    if (frameProxy != null) {
      try {
        final ThreadReferenceProxy threadReferenceProxy = frameProxy.threadProxy();
        frameCount = threadReferenceProxy.frameCount();
        frameIndex = frameProxy.getFrameIndex();
       }
       catch (EvaluateException e) {
         // ignored
       }
    }
    final boolean isInitial = !fromTree.frameIdEquals(frameCount, frameIndex);
    DescriptorTree descriptorTree = new DescriptorTree(isInitial);
    descriptorTree.setFrameId(frameCount, frameIndex);
    return descriptorTree;
  }

  @Override
  public ArrayElementDescriptorImpl getArrayItemDescriptor(NodeDescriptor parent, ArrayReference array, int index) {
    return getDescriptor(parent, new ArrayItemData(array, index));
  }

  @Override
  public FieldDescriptorImpl getFieldDescriptor(NodeDescriptor parent, ObjectReference objRef, Field field) {
    final DescriptorData<FieldDescriptorImpl> descriptorData;
    if (objRef == null ) {
      if (!field.isStatic()) {
        LOG.error("Object reference is null for non-static field: " + field);
      }
      descriptorData = new StaticFieldData(field);
    }
    else {
      descriptorData = new FieldData(objRef, field);
    }
    return getDescriptor(parent, descriptorData);
  }

  @Override
  public LocalVariableDescriptorImpl getLocalVariableDescriptor(NodeDescriptor parent, LocalVariableProxy local) {
    return getDescriptor(parent, new LocalData((LocalVariableProxyImpl)local));
  }

  public ArgumentValueDescriptorImpl getArgumentValueDescriptor(NodeDescriptor parent, int index, Value value, final String name) {
    return getDescriptor(parent, new ArgValueData(index, value, name));
  }

  public StackFrameDescriptorImpl getStackFrameDescriptor(@Nullable NodeDescriptorImpl parent, @NotNull StackFrameProxyImpl frameProxy) {
    return getDescriptor(parent, new StackFrameData(frameProxy));
  }

  public StaticDescriptorImpl getStaticDescriptor(NodeDescriptorImpl parent, ReferenceType refType) {//static is unique
    return getDescriptor(parent, new StaticData(refType));
  }

  public ValueDescriptorImpl getThisDescriptor(NodeDescriptorImpl parent, Value value) {
    return getDescriptor(parent, new ThisData());
  }

  public ValueDescriptorImpl getMethodReturnValueDescriptor(NodeDescriptorImpl parent, Method method, Value value) {
    return getDescriptor(parent, new MethodReturnValueData(method, value));
  }

  public ValueDescriptorImpl getThrownExceptionObjectDescriptor(NodeDescriptorImpl parent, ObjectReference exceptionObject) {
    return getDescriptor(parent, new ThrownExceptionValueData(exceptionObject));
  }

  public ThreadDescriptorImpl getThreadDescriptor(NodeDescriptorImpl parent, ThreadReferenceProxyImpl thread) {
    return getDescriptor(parent, new ThreadData(thread));
  }

  public ThreadGroupDescriptorImpl getThreadGroupDescriptor(NodeDescriptorImpl parent, ThreadGroupReferenceProxyImpl group) {
    return getDescriptor(parent, new ThreadGroupData(group));
  }

  @Override
  public UserExpressionDescriptor getUserExpressionDescriptor(NodeDescriptor parent, final DescriptorData<UserExpressionDescriptor> data) {
    return getDescriptor(parent, data);
  }

  public WatchItemDescriptor getWatchItemDescriptor(NodeDescriptor parent, TextWithImports text, @Nullable Value value){
    return getDescriptor(parent, new WatchItemData(text, value));
  }
  
  private static class DescriptorTreeSearcher {
    private final MarkedDescriptorTree myDescriptorTree;

    private final HashMap<NodeDescriptor, NodeDescriptor> mySearchedDescriptors = new HashMap<NodeDescriptor, NodeDescriptor>();

    public DescriptorTreeSearcher(MarkedDescriptorTree descriptorTree) {
      myDescriptorTree = descriptorTree;
    }

    @Nullable
    public <T extends NodeDescriptor> T search(NodeDescriptor parent, T descriptor, DescriptorKey<T> key) {
      final T result;
      if(parent == null) {
        result = myDescriptorTree.getChild(null, key);
      }
      else {
        final NodeDescriptor parentDescriptor = getSearched(parent);
        result = parentDescriptor != null ? myDescriptorTree.getChild(parentDescriptor, key) : null;
      }
      if(result != null) {
        mySearchedDescriptors.put(descriptor, result);
      }
      return result;
    }

    protected NodeDescriptor getSearched(NodeDescriptor parent) {
      return mySearchedDescriptors.get(parent);
    }

    public void clear() {
      mySearchedDescriptors.clear();
      myDescriptorTree.clear();
    }
  }

  private class DisplayDescriptorTreeSearcher extends DescriptorTreeSearcher {
    public DisplayDescriptorTreeSearcher(MarkedDescriptorTree descriptorTree) {
      super(descriptorTree);
    }

    @Override
    protected NodeDescriptor getSearched(NodeDescriptor parent) {
      NodeDescriptor searched = super.getSearched(parent);
      if(searched == null) {
        return myDescriptorSearcher.getSearched(parent);
      }
      return searched;
    }
  }
}
