// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.google.dart.compiler.resolver;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.dart.compiler.DartCompilerContext;
import com.google.dart.compiler.ast.ASTVisitor;
import com.google.dart.compiler.ast.DartClass;
import com.google.dart.compiler.ast.DartFunctionTypeAlias;
import com.google.dart.compiler.ast.DartTypeNode;
import com.google.dart.compiler.ast.DartTypeParameter;
import com.google.dart.compiler.ast.DartUnit;
import com.google.dart.compiler.type.InterfaceType;
import com.google.dart.compiler.type.Type;
import com.google.dart.compiler.type.TypeKind;

import java.util.List;
import java.util.Set;

/**
 * Resolves the super class, interfaces, default implementation and
 * bounds type parameters of classes in a DartUnit.
 */
public class SupertypeResolver {
  private static final Set<String> BLACK_LISTED_TYPES = ImmutableSet.of(
      "dynamic",
      "Function",
      "bool",
      "num",
      "int",
      "double",
      "String");

  private ResolutionContext topLevelContext;
  private CoreTypeProvider typeProvider;

  public void exec(DartUnit unit, DartCompilerContext context, CoreTypeProvider typeProvider) {
    exec(unit, context, unit.getLibrary().getElement().getScope(), typeProvider);
  }

  public void exec(DartUnit unit, DartCompilerContext compilerContext, Scope libraryScope,
                   CoreTypeProvider typeProvider) {
    this.typeProvider = typeProvider;
    this.topLevelContext = new ResolutionContext(libraryScope, compilerContext, typeProvider);
    unit.accept(new ClassElementResolver());
  }

  // Resolves super class, interfaces and default class of all classes.
  private class ClassElementResolver extends ASTVisitor<Void> {
    @Override
    public Void visitClass(DartClass node) {
      ClassElement classElement = node.getElement();

      // Make sure that the type parameters are in scope before resolving the
      // super class and interfaces
      ResolutionContext classContext = topLevelContext.extend(classElement);

      DartTypeNode superclassNode = node.getSuperclass();
      InterfaceType supertype;
      if (superclassNode == null) {
        supertype = typeProvider.getObjectType();
        if (supertype.equals(classElement.getType())) {
          // Object has no supertype.
          supertype = null;
        }
      } else {
        supertype = classContext.resolveClass(superclassNode, false, false);
        supertype.getClass(); // Quick null check.
      }
      if (supertype != null) {
        if (Elements.isTypeNode(superclassNode, BLACK_LISTED_TYPES)
            && !Elements.isCoreLibrarySource(node.getSourceInfo().getSource())) {
          topLevelContext.onError(
              superclassNode,
              ResolverErrorCode.BLACK_LISTED_EXTENDS,
              superclassNode);
        }
        classElement.setSupertype(supertype);
      } else {
        assert classElement.getName().equals("Object") : classElement;
      }

      if (node.getDefaultClass() != null) {
        Element defaultClassElement = classContext.resolveName(node.getDefaultClass().getExpression());
        if (ElementKind.of(defaultClassElement).equals(ElementKind.CLASS)) {
          Elements.setDefaultClass(classElement, (InterfaceType)defaultClassElement.getType());
          node.getDefaultClass().setType(defaultClassElement.getType());
        }
      }

      if (node.getInterfaces() != null) {
        Set<InterfaceType> seenImplement = Sets.newHashSet();
        for (DartTypeNode intNode : node.getInterfaces()) {
          InterfaceType intType = classContext.resolveInterface(intNode, false, false);
          // May be type which can not be used as interface.
          if (Elements.isTypeNode(intNode, BLACK_LISTED_TYPES)
              && !Elements.isCoreLibrarySource(node.getSourceInfo().getSource())) {
            topLevelContext.onError(intNode, ResolverErrorCode.BLACK_LISTED_IMPLEMENTS, intNode);
            continue;
          }
          // May be unresolved type, error already reported, ignore.
          if (intType.getKind() == TypeKind.DYNAMIC) {
            continue;
          }
          // check for uniqueness
          if (!classElement.isInterface()) {
            if (seenImplement.contains(intType)) {
              topLevelContext.onError(intNode, ResolverErrorCode.DUPLICATE_IMPLEMENTS_TYPE);
              continue;
            }
            seenImplement.add(intType);
          }
          // OK, add
          Elements.addInterface(classElement, intType);
        }
      }
      setBoundsOnTypeParameters(classElement.getTypeParameters(), classContext);
      return null;
    }

    @Override
    public Void visitFunctionTypeAlias(DartFunctionTypeAlias node) {
      ResolutionContext resolutionContext = topLevelContext.extend(node.getElement());
      Elements.addInterface(node.getElement(), typeProvider.getFunctionType());
      setBoundsOnTypeParameters(node.getElement().getTypeParameters(), resolutionContext);
      return null;
    }
  }

  private void setBoundsOnTypeParameters(List<Type> typeParameters,
                                         ResolutionContext resolutionContext) {
    for (Type typeParameter : typeParameters) {
      TypeVariableNodeElement variable = (TypeVariableNodeElement) typeParameter.getElement();
      DartTypeParameter typeParameterNode = (DartTypeParameter) variable.getNode();
      DartTypeNode boundNode = typeParameterNode.getBound();
      if (boundNode != null) {
        Type bound =
            resolutionContext.resolveType(
                boundNode,
                false,
                false,
                true,
                ResolverErrorCode.NO_SUCH_TYPE,
                ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
        boundNode.setType(bound);
      }
    }
  }

}
