// Copyright (c) 2018, 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.

import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/type_system.dart';

class InheritanceOverrideVerifier {
  final StrongTypeSystemImpl _typeSystem;
  final ErrorReporter _reporter;

  /// Cached instance interfaces for [InterfaceType].
  final Map<InterfaceType, _Interface> _interfaces = {};

  InheritanceOverrideVerifier(this._typeSystem, this._reporter);

  void verifyUnit(CompilationUnit unit) {
    for (var declaration in unit.declarations) {
      if (declaration is ClassDeclaration) {
        _verifyClass(declaration.name,
            withClause: declaration.withClause, members: declaration.members);
      } else if (declaration is ClassTypeAlias) {
        _verifyClass(declaration.name, withClause: declaration.withClause);
      } else if (declaration is MixinDeclaration) {
        _verifyClass(declaration.name, members: declaration.members);
      }
    }
  }

  /// Check that the given [member] is a valid override of the corresponding
  /// instance members in each of [allSuperinterfaces].
  void _checkDeclaredMember(
    List<InterfaceType> allSuperinterfaces,
    AstNode node,
    ExecutableElement member,
  ) {
    if (member == null) return;
    if (member.isStatic) return;

    var name = member.name;
    for (var supertype in allSuperinterfaces) {
      var superMember = _getInstanceMember(supertype, name);
      if (superMember != null && superMember.isAccessibleIn(member.library)) {
        // The case when members have different kinds is reported in verifier.
        if (member.kind != superMember.kind) {
          continue;
        }

        if (!_typeSystem.isOverrideSubtypeOf(member.type, superMember.type)) {
          _reporter.reportErrorForNode(
            CompileTimeErrorCode.INVALID_OVERRIDE,
            node,
            [
              name,
              member.enclosingElement.name,
              member.type.displayName,
              superMember.enclosingElement.name,
              superMember.type.displayName
            ],
          );
        }
      }
    }
  }

  /// Check that instance members of [type] are valid overrides of the
  /// corresponding instance members in each of [allSuperinterfaces].
  void _checkDeclaredMembers(
    List<InterfaceType> allSuperinterfaces,
    AstNode node,
    InterfaceTypeImpl type,
  ) {
    for (var method in type.methods) {
      _checkDeclaredMember(allSuperinterfaces, node, method);
    }
    for (var accessor in type.accessors) {
      _checkDeclaredMember(allSuperinterfaces, node, accessor);
    }
  }

  /// Return the instance member given the [name], defined in the [type],
  /// or `null` if the [type] does not define a member with the [name], or
  /// if it is not an instance member.
  ExecutableElement _getInstanceMember(InterfaceType type, String name) {
    ExecutableElement result;
    if (name.endsWith('=')) {
      name = name.substring(0, name.length - 1);
      result = type.getSetter(name);
    } else {
      result = type.getMethod(name) ?? type.getGetter(name);
    }
    if (result != null && result.isStatic) {
      result = null;
    }
    return result;
  }

  /// Return the interface of the given [type], for the [consumerLibrary].
  _Interface _getInterface(InterfaceType type, LibraryElement consumerLibrary) {
    if (type == null) return new _Interface({}, []);

    var result = _interfaces[type];
    if (result != null) return result;

    var map = <String, FunctionType>{};
    var conflicts = <_Conflict>[];
    _interfaces[type] = new _Interface(map, conflicts);

    // If a class declaration has a member declaration, the signature of that
    // member declaration becomes the signature in the interface.
    {
      void addTypeMember(ExecutableElement member) {
        if (member.isAccessibleIn(consumerLibrary) && !member.isStatic) {
          map[member.name] = member.type;
        }
      }

      type.methods.forEach(addTypeMember);
      type.accessors.forEach(addTypeMember);
    }

    var inheritedCandidates = <String, List<FunctionType>>{};
    void addSuperinterfaceMember(String name, FunctionType candidate) {
      // If name is in the [map], then it is defined in the [type] itself.
      // Don't consider candidates from direct superinterfaces.
      // The version defined in the type might be invalid, we check elsewhere.
      if (map.containsKey(name)) return;

      var candidates = inheritedCandidates[name];
      if (candidates == null) {
        candidates = <FunctionType>[];
        inheritedCandidates[name] = candidates;
      }
      candidates.add(candidate);
    }

    var library = type.element.library;
    void addSuperinterfaceMembers(InterfaceType superinterface) {
      _getInterface(superinterface, library)
          .map
          .forEach(addSuperinterfaceMember);
    }

    // Fill candidates for each instance name.
    addSuperinterfaceMembers(type.superclass);
    type.superclassConstraints.forEach(addSuperinterfaceMembers);
    type.mixins.forEach(addSuperinterfaceMembers);
    type.interfaces.forEach(addSuperinterfaceMembers);

    // If a class declaration does not have a member declaration with a
    // particular name, but some super-interfaces do have a member with that
    // name, it's a compile-time error if there is no signature among the
    // super-interfaces that is a valid override of all the other
    // super-interface signatures with the same name. That "most specific"
    // signature becomes the signature of the class's interface.
    for (var name in inheritedCandidates.keys) {
      var candidates = inheritedCandidates[name];

      bool allGetters = true;
      bool allMethods = true;
      bool allSetters = true;
      for (var candidate in candidates) {
        var kind = candidate.element.kind;
        if (kind != ElementKind.GETTER) {
          allGetters = false;
        }
        if (kind != ElementKind.METHOD) {
          allMethods = false;
        }
        if (kind != ElementKind.SETTER) {
          allSetters = false;
        }
      }

      if (allSetters) {
        // OK, setters don't conflict with anything.
      } else if (!(allGetters || allMethods)) {
        FunctionType getterType;
        FunctionType methodType;
        for (var candidate in candidates) {
          var kind = candidate.element.kind;
          if (kind == ElementKind.GETTER) {
            getterType ??= candidate;
          }
          if (kind == ElementKind.METHOD) {
            methodType ??= candidate;
          }
        }
        conflicts.add(new _Conflict(name, candidates, getterType, methodType));
        continue;
      }

      FunctionType validOverride;
      for (var i = 0; i < candidates.length; i++) {
        validOverride = candidates[i];
        for (var j = 0; j < candidates.length; j++) {
          var candidate = candidates[j];
          if (!_typeSystem.isOverrideSubtypeOf(validOverride, candidate)) {
            validOverride = null;
            break;
          }
        }
        if (validOverride != null) {
          break;
        }
      }

      if (validOverride != null) {
        map[name] = validOverride;
      } else {
        conflicts.add(new _Conflict(name, candidates));
      }
    }

    return new _Interface(map, conflicts);
  }

  void _reportInconsistentInheritance(AstNode node, _Conflict conflict) {
    var name = conflict.name;

    if (conflict.getter != null && conflict.method != null) {
      _reporter.reportErrorForNode(
        CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
        node,
        [
          name,
          conflict.getter.element.enclosingElement.name,
          conflict.method.element.enclosingElement.name
        ],
      );
    } else {
      var candidatesStr = conflict.candidates.map((candidate) {
        var className = candidate.element.enclosingElement.name;
        return '$className.$name (${candidate.displayName})';
      }).join(', ');

      _reporter.reportErrorForNode(
        CompileTimeErrorCode.INCONSISTENT_INHERITANCE,
        node,
        [name, candidatesStr],
      );
    }
  }

  void _verifyClass(SimpleIdentifier classNameNode,
      {List<ClassMember> members: const [], WithClause withClause}) {
    ClassElementImpl element = classNameNode.staticElement;
    LibraryElement library = element.library;
    InterfaceTypeImpl type = element.type;

    var allSuperinterfaces = <InterfaceType>[];

    // Add all superinterfaces of the direct supertype.
    if (type.superclass != null) {
      ClassElementImpl.collectAllSupertypes(
          allSuperinterfaces, type.superclass, null);
    }

    // Each mixin in `class C extends S with M0, M1, M2 {}` is equivalent to:
    //   class S&M0 extends S { ...members of M0... }
    //   class S&M1 extends S&M0 { ...members of M1... }
    //   class S&M2 extends S&M1 { ...members of M2... }
    //   class C extends S&M2 { ...members of C... }
    // So, we need to check members of each mixin against superinterfaces
    // of `S`, and superinterfaces of all previous mixins.
    var mixinNodes = withClause?.mixinTypes;
    var mixinTypes = type.mixins;
    for (var i = 0; i < mixinTypes.length; i++) {
      _checkDeclaredMembers(allSuperinterfaces, mixinNodes[i], mixinTypes[i]);
      ClassElementImpl.collectAllSupertypes(
          allSuperinterfaces, mixinTypes[i], null);
    }

    // Add all superinterfaces of the direct class interfaces.
    for (var interface in type.interfaces) {
      ClassElementImpl.collectAllSupertypes(
          allSuperinterfaces, interface, null);
    }

    // Check the members if the class itself, against all the previously
    // collected superinterfaces of the supertype, mixins, and interfaces.
    for (var member in members) {
      if (member is FieldDeclaration) {
        var fieldList = member.fields;
        for (var field in fieldList.variables) {
          FieldElement fieldElement = field.declaredElement;
          _checkDeclaredMember(
              allSuperinterfaces, fieldList, fieldElement.getter);
          _checkDeclaredMember(
              allSuperinterfaces, fieldList, fieldElement.setter);
        }
      } else if (member is MethodDeclaration) {
        _checkDeclaredMember(
            allSuperinterfaces, member, member.declaredElement);
      }
    }

    // Compute the interface of the class.
    var interfaceMembers = _getInterface(type, element.library);

    // Report conflicts between direct superinterfaces of the class.
    for (var conflict in interfaceMembers.conflicts) {
      _reportInconsistentInheritance(classNameNode, conflict);
    }

    // TODO(scheglov) isMixin must be also isAbstract.
    if (!element.isAbstract && !element.isMixin) {
      for (var name in interfaceMembers.map.keys) {
        var concreteElement = type.lookUpInheritedMember(name, library,
            concrete: true, thisType: true, setter: name.endsWith('='));

        // TODO(scheglov) handle here instead of ErrorVerifier?
        if (concreteElement == null) {
          continue;
        }
        // TODO(scheglov) Why InterfaceType even returns statics?
        if (concreteElement.isStatic) {
          continue;
        }

        var concreteType = concreteElement.type;
        var interfaceType = interfaceMembers.map[name];

        // The case when members have different kinds is reported in verifier.
        if (concreteType.element.kind != interfaceType.element.kind) {
          continue;
        }

        // If a class declaration is not abstract, and the interface has a
        // member declaration named `m`, then:
        // 1. if the class contains a non-overridden member whose signature is
        //    not a valid override of the interface member signature for `m`,
        //    then it's a compile-time error.
        // 2. if the class contains no member named `m`, and the class member
        //    for `noSuchMethod` is the one declared in `Object`, then it's a
        //    compile-time error. TODO(scheglov) implement this
        if (!_typeSystem.isOverrideSubtypeOf(concreteType, interfaceType)) {
          _reporter.reportErrorForNode(
            CompileTimeErrorCode.INVALID_OVERRIDE,
            classNameNode,
            [
              name,
              concreteElement.enclosingElement.name,
              concreteType.displayName,
              interfaceType.element.enclosingElement.name,
              interfaceType.displayName
            ],
          );
        }
      }
    }
  }
}

/// Description of a failure to find a valid override from superinterfaces.
class _Conflict {
  /// The name of an instance member for which we failed to find a valid
  /// override.
  final String name;

  /// The list of candidates for a valid override for a member [name].  It has
  /// at least two items, because otherwise the only candidate is always valid.
  final List<FunctionType> candidates;

  final FunctionType getter;
  final FunctionType method;

  _Conflict(this.name, this.candidates, [this.getter, this.method]);
}

/// The instance interface of an [InterfaceType].
class _Interface {
  final Map<String, FunctionType> map;
  final List<_Conflict> conflicts;

  _Interface(this.map, this.conflicts);
}
