package com.jetbrains.python.codeInsight;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyElementImpl;
import com.jetbrains.python.psi.resolve.ResolveImportUtil;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;

/**
 * @author Dennis.Ushakov
 */
public class PyDynamicMember {
  private String myName;
  private final boolean myResolveToInstance;
  private final String myTypeName;

  private final String myResolveShortName;
  private final String myResolveModuleName;

  public PyDynamicMember(final String name, final String type, final boolean resolveToInstance) {
    this(name, type, type, resolveToInstance);
  }

  public PyDynamicMember(final String name, final String type, final String resolveTo, final boolean resolveToInstance) {
    myName = name;
    myResolveToInstance = resolveToInstance;
    myTypeName = type;

    int split = resolveTo.lastIndexOf('.');
    myResolveShortName = resolveTo.substring(split + 1);
    myResolveModuleName = resolveTo.substring(0, split);
  }

  public String getName() {
    return myName;
  }

  public Icon getIcon() {
    return IconLoader.getIcon("/nodes/method.png");
  }

  @Nullable
  public PsiElement resolve(Project project, PyClass modelClass) {
    PyClass targetClass = PyClassNameIndex.findClass(myTypeName, project);
    if (targetClass != null) {
      return new MyInstanceElement(targetClass, findResolveTarget(modelClass));
    }
    return null;
  }

  @Nullable
  private PsiElement findResolveTarget(PyClass clazz) {
    PsiElement module = ResolveImportUtil.resolveInRoots(clazz, myResolveModuleName);
    if (module instanceof PsiDirectory) {
      module = PyUtil.turnDirIntoInit(module);
    }
    if (module == null) return null;
    final PyFile file = (PyFile)module;
    for (PyStatement statement : file.getStatements()) {
      final String name = statement.getName();
      if (myResolveShortName.equals(name)) return statement;
    }
    return module;
  }

  public String getShortType() {
    int pos = myTypeName.lastIndexOf('.');
    return myTypeName.substring(pos+1);
  }

  private class MyInstanceElement extends PyElementImpl implements PyExpression {
    private final PyClass myClass;
    public MyInstanceElement(PyClass clazz, PsiElement resolveTarget) {
      super(resolveTarget != null ? resolveTarget.getNode() : clazz.getNode());
      myClass = clazz;
    }

    public PyType getType() {
      return new PyClassType(myClass, !myResolveToInstance);
    }
  }
}

@@ -819,24 +819,61 @@
 eModuleName;
+%0A  private final PsiElement myTarget;
 %0A%0A  public P
@@ -1379,16 +1379,275 @@
  split);
+%0A%0A    myTarget = null;%0A  %7D%0A%0A  public PyDynamicMember(final String name, final PsiElement target) %7B%0A    myName = name;%0A    myTarget = target;%0A    myResolveToInstance = false;%0A    myTypeName = null;%0A    myResolveModuleName = null;%0A    myResolveShortName = null;
 %0A  %7D%0A%0A  
@@ -1854,24 +1854,81 @@
 delClass) %7B%0A
+    if (myTarget != null) %7B%0A      return myTarget;%0A    %7D%0A
     PyClass 
@@ -2642,32 +2642,44 @@
 rn module;%0A  %7D%0A%0A
+  @Nullable%0A
   public String 
@@ -2691,24 +2691,79 @@
 ortType() %7B%0A
+    if (myTypeName == null) %7B%0A      return null;%0A    %7D%0A
     int pos 
@@ -2828,17 +2828,19 @@
 ring(pos
-+
+ + 
 1);%0A  %7D%0A

resolve and completion for Django settings (PY-563)