/*
 * Copyright 2000-2013 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.jetbrains.python;

import com.intellij.psi.PsiFile;
import com.jetbrains.python.documentation.PythonDocumentationProvider;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.types.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author yole
 */
public class PyTypeParserTest extends PyTestCase {
  public void testClassType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "MyObject");
    assertClassType(type, "MyObject");
  }

  private static void assertClassType(PyType type, final String name) {
    assertNotNull(type);
    assertEquals(name, ((PyClassType)type).getPyClass().getName());
  }

  public void testTupleType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyTupleType type = (PyTupleType)PyTypeParser.getTypeByName(myFixture.getFile(), "(str, MyObject)");
    assertEquals(2, type.getElementCount());
    assertClassType(type.getElementType(0), "str");
    assertClassType(type.getElementType(1), "MyObject");
  }

  public void testListType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyCollectionType type = (PyCollectionType) PyTypeParser.getTypeByName(myFixture.getFile(), "list of MyObject");
    assertClassType(type, "list");
    assertClassType(type.getElementType(getTypeEvalContext()), "MyObject");
  }

  public void testDictType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyCollectionType type = (PyCollectionType) PyTypeParser.getTypeByName(myFixture.getFile(), "dict from str to MyObject");
    assertNotNull(type);
    assertClassType(type, "dict");
    final PyType elementType = type.getElementType(getTypeEvalContext());
    assertInstanceOf(elementType, PyTupleType.class);
    final PyTupleType tupleType = (PyTupleType)elementType;
    assertEquals(2, tupleType.getElementCount());
    assertClassType(tupleType.getElementType(0), "str");
    assertClassType(tupleType.getElementType(1), "MyObject");
  }

  private TypeEvalContext getTypeEvalContext() {
    return TypeEvalContext.userInitiated(myFixture.getFile());
  }

  public void testUnionType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyUnionType type = (PyUnionType)PyTypeParser.getTypeByName(myFixture.getFile(), "MyObject or str");
    assertNotNull(type);
    final Collection<PyType> members = type.getMembers();
    assertEquals(2, members.size());
    final List<PyType> list = new ArrayList<PyType>(members);
    assertClassType(list.get(0), "MyObject");
    assertClassType(list.get(1), "str");
  }

  public void testNoneType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "None");
    assertNotNull(type);
    assertInstanceOf(type, PyNoneType.class);
  }

  public void testIntegerType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "integer");
    assertClassType(type, "int");
  }

  public void testStringType() {
    // Python 2
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "string");
    assertNotNull(type);
    assertInstanceOf(type, PyUnionType.class);
    final PyUnionType unionType = (PyUnionType)type;
    final ArrayList<PyType> types = new ArrayList<PyType>(unionType.getMembers());
    assertClassType(types.get(0), "str");
    assertClassType(types.get(1), "unicode");
  }

  public void testBooleanType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "boolean");
    assertClassType(type, "bool");
  }

  public void testDictionaryType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "dictionary");
    assertClassType(type, "dict");
  }

  public void testQualifiedNotImportedType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyTypeParser.ParseResult result = PyTypeParser.parse(myFixture.getFile(), "collections.Iterable");
    final PyType type = result.getType();
    assertClassType(type, "Iterable");
    assertEquals(2, result.getTypes().size());
  }

  public void testUnqualifiedNotImportedType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "Iterable");
    assertClassType(type, "Iterable");
  }

  public void testTypeSubparts() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final String s = "list of (MyObject, collections.Iterable of MyObject, int) or None";
    PyTypeParser.ParseResult result = PyTypeParser.parse(myFixture.getFile(), s);
    assertEquals(7, result.getTypes().values().size());
  }

  public void testGenericType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "T");
    assertNotNull(type);
    assertInstanceOf(type, PyGenericType.class);
    assertEquals("T", type.getName());
  }

  // PY-4223
  public void testSphinxFormattedType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final String s = "(MyObject, :class:`MyObject`, :py:class:`MyObject`, :class:`!MyObject`, :py:class:`~MyObject`)";
    final PyTupleType type = (PyTupleType)PyTypeParser.getTypeByName(myFixture.getFile(), s);
    assertNotNull(type);
    final int n = type.getElementCount();
    assertEquals(5, n);
    for (int i = 0; i < n; i++) {
      assertClassType(type.getElementType(i), "MyObject");
    }
  }

  // PY-7950
  public void testUnionWithUnresolved() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "Unresolved or int");
    assertNotNull(type);
    assertInstanceOf(type, PyUnionType.class);
    final List<PyType> members = new ArrayList<PyType>(((PyUnionType)type).getMembers());
    assertEquals(2, members.size());
    assertNull(members.get(0));
    assertClassType(members.get(1), "int");
  }

  public void testUnionParamPriority() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType t1 = PyTypeParser.getTypeByName(myFixture.getFile(), "list of int or list of str");
    assertInstanceOf(t1, PyUnionType.class);
    final PyType t2 = PyTypeParser.getTypeByName(myFixture.getFile(), "list of str or int");
    assertInstanceOf(t2, PyUnionType.class);
  }

  public void testParenthesesPriority() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "list of (str or int)");
    assertInstanceOf(type, PyCollectionType.class);
    final PyCollectionType collectionType = (PyCollectionType)type;
    assertNotNull(collectionType);
    assertEquals("list", collectionType.getName());
    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
    assertInstanceOf(elementType, PyUnionType.class);
  }

  public void testBoundedGeneric() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "T <= str or unicode");
    assertNotNull(type);
    assertInstanceOf(type, PyGenericType.class);
    final PyGenericType genericType = (PyGenericType)type;
    final PyType bound = genericType.getBound();
    assertInstanceOf(bound, PyUnionType.class);
  }

  public void testBracketSingleParam() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "list[int]");
    assertInstanceOf(type, PyCollectionType.class);
    final PyCollectionType collectionType = (PyCollectionType)type;
    assertNotNull(collectionType);
    assertEquals("list", collectionType.getName());
    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
    assertNotNull(elementType);
    assertEquals("int", elementType.getName());
  }

  public void testBracketMultipleParams() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "dict[str, int]");
    assertInstanceOf(type, PyCollectionType.class);
    final PyCollectionType collectionType = (PyCollectionType)type;
    assertNotNull(collectionType);
    assertEquals("dict", collectionType.getName());
    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
    assertNotNull(elementType);
    assertInstanceOf(elementType, PyTupleType.class);
    final PyTupleType tupleType = (PyTupleType)elementType;
    final PyType first = tupleType.getElementType(0);
    assertNotNull(first);
    assertEquals("str", first.getName());
    final PyType second = tupleType.getElementType(1);
    assertNotNull(second);
    assertEquals("int", second.getName());
  }

  public void testUnionOrOperator() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyUnionType type = (PyUnionType)PyTypeParser.getTypeByName(myFixture.getFile(), "MyObject | str | unicode");
    assertNotNull(type);
    final Collection<PyType> members = type.getMembers();
    assertEquals(3, members.size());
    final List<PyType> list = new ArrayList<PyType>(members);
    assertClassType(list.get(0), "MyObject");
    assertClassType(list.get(1), "str");
    assertClassType(list.get(2), "unicode");
  }

  public void testCallableType() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "(int, T) -> T");
    assertInstanceOf(type, PyCallableType.class);
    final PyCallableType callableType = (PyCallableType)type;
    assertNotNull(callableType);
    final TypeEvalContext context = getTypeEvalContext();
    final PyType returnType = callableType.getReturnType(context);
    assertInstanceOf(returnType, PyGenericType.class);
    final List<PyCallableParameter> parameterTypes = callableType.getParameters(context);
    assertNotNull(parameterTypes);
    assertEquals(2, parameterTypes.size());
    final PyType type0 = parameterTypes.get(0).getType(context);
    assertNotNull(type0);
    assertEquals("int", type0.getName());
    final PyType type1 = parameterTypes.get(1).getType(context);
    assertNotNull(type1);
    assertEquals("T", type1.getName());
  }

  public void testCallableWithoutArgs() {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "() -> int");
    assertInstanceOf(type, PyCallableType.class);
    final PyCallableType callableType = (PyCallableType)type;
    assertNotNull(callableType);
    final PyType returnType = callableType.getReturnType(getTypeEvalContext());
    assertNotNull(returnType);
    assertEquals("int", returnType.getName());
    final List<PyCallableParameter> parameterTypes = callableType.getParameters(getTypeEvalContext());
    assertNotNull(parameterTypes);
    assertEquals(0, parameterTypes.size());
  }

  public void testQualifiedUserSkeletonsClass() {
    doTest("Iterator[int]", "collections.Iterator[int]");
  }

  public void testUnqualifiedUserSkeletonsClass() {
    doTest("Iterator[int]", "Iterator[int]");
  }

  private void doTest(final String expectedType, final String text) {
    myFixture.configureByFile("typeParser/typeParser.py");
    final PsiFile file = myFixture.getFile();
    final PyType type = PyTypeParser.getTypeByName(file, text);
    TypeEvalContext context = TypeEvalContext.userInitiated(file).withTracing();
    final String actualType = PythonDocumentationProvider.getTypeName(type, context);
    assertEquals(expectedType, actualType);
  }
}
