/*
 * @author max
 */
package com.jetbrains.python.psi.impl.stubs;

import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.util.io.DataInputOutputUtil;
import com.intellij.util.io.PersistentStringEnumerator;
import com.intellij.util.io.StringRef;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.PyStubElementType;
import com.jetbrains.python.psi.impl.PyClassImpl;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.stubs.PyClassStub;
import com.jetbrains.python.psi.stubs.PySuperClassIndex;

import java.io.IOException;

public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass> {
  public PyClassElementType() {
    super("CLASS_DECLARATION");
  }

  public PsiElement createElement(final ASTNode node) {
    return new PyClassImpl(node);
  }

  public PyClass createPsi(final PyClassStub stub) {
    return new PyClassImpl(stub);
  }

  public PyClassStub createStub(final PyClass psi, final StubElement parentStub) {
    final PyExpression[] exprs = psi.getSuperClassExpressions();
    String[] superClasses = new String[exprs.length];
    for(int i=0; i<exprs.length; i++) {
      final PyExpression expression = exprs[i];
      if (expression instanceof PyReferenceExpression) {
        superClasses [i] = ((PyReferenceExpression) expression).getReferencedName();
      }
      else {
        superClasses [i] = expression.getText();
      }
    }
    return new PyClassStubImpl(psi.getName(), parentStub, superClasses);
  }

  public void serialize(final PyClassStub pyClassStub, final StubOutputStream dataStream) throws IOException {
    dataStream.writeName(pyClassStub.getName());
    final String[] classes = pyClassStub.getSuperClasses();
    dataStream.writeByte(classes.length);
    for(String s: classes) {
      dataStream.writeName(s);
    }
  }

  public PyClassStub deserialize(final StubInputStream dataStream, final StubElement parentStub) throws IOException {
    String name = StringRef.toString(dataStream.readName());
    int superClassCount = dataStream.readByte();
    String[] superClasses = new String[superClassCount];
    for(int i=0; i<superClassCount; i++) {
      superClasses[i] = StringRef.toString(dataStream.readName());
    }
    return new PyClassStubImpl(name, parentStub, superClasses);
  }

  public void indexStub(final PyClassStub stub, final IndexSink sink) {
    final String name = stub.getName();
    if (name != null) {
      sink.occurrence(PyClassNameIndex.KEY, name);
    }
    for(String s: stub.getSuperClasses()) {
      sink.occurrence(PySuperClassIndex.KEY, s);
    }
  }
}
@@ -245,27 +245,26 @@
 i.stubs.Stub
-Out
+In
 putStream;%0Ai
@@ -300,124 +300,20 @@
 Stub
-InputStream;%0Aimport com.intellij.util.io.DataInputOutputUtil;%0Aimport com.intellij.util.io.PersistentStringEnumerator
+OutputStream
 ;%0Aim
@@ -784,16 +784,67 @@
 ception;
+%0Aimport java.util.ArrayList;%0Aimport java.util.List;
 %0A%0Apublic
@@ -1323,32 +1323,36 @@
 ions();%0A    
+List%3C
 String
-%5B%5D
+%3E
  superClasse
@@ -1363,76 +1363,38 @@
 new 
-String%5Bexprs.length%5D;%0A    for(int i=0; i%3Cexprs.length; i++) %7B%0A      
+ArrayList%3CString%3E();%0A    for (
 fina
@@ -1423,19 +1423,18 @@
 ion 
-=
+:
  exprs
-%5Bi%5D;
+) %7B
 %0A   
@@ -1495,32 +1495,43 @@
         
-superClasses %5Bi%5D
+final String referencedName
  = ((PyR
@@ -1549,17 +1549,16 @@
 ression)
- 
 expressi
@@ -1592,23 +1592,42 @@
     
-%7D%0A      else
+  if (referencedName != null)
  %7B%0A
+  
     
@@ -1646,36 +1646,39 @@
 sses
- %5Bi%5D = expression.getText();
+.add(referencedName);%0A        %7D
 %0A   
@@ -1750,32 +1750,73 @@
 ub, superClasses
+.toArray(new String%5BsuperClasses.size()%5D)
 );%0A  %7D%0A%0A  public

fix exception on creating stub for incomplete class declaration