// 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.

library fasta.class_hierarchy_builder;

import 'package:kernel/ast.dart'
    show Library, Member, Name, Procedure, ProcedureKind;

import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;

import '../messages.dart'
    show
        LocatedMessage,
        messageDeclaredMemberConflictsWithInheritedMember,
        messageDeclaredMemberConflictsWithInheritedMemberCause,
        messageInheritedMembersConflict,
        messageInheritedMembersConflictCause1,
        messageInheritedMembersConflictCause2,
        templateMissingImplementationCause,
        templateMissingImplementationNotAbstract;

import '../names.dart' show noSuchMethodName;

import '../scope.dart' show Scope;

import 'kernel_builder.dart'
    show
        Declaration,
        LibraryBuilder,
        KernelClassBuilder,
        KernelNamedTypeBuilder,
        KernelTypeBuilder;

int compareDeclarations(Declaration a, Declaration b) {
  return ClassHierarchy.compareMembers(a.target, b.target);
}

ProcedureKind memberKind(Member member) {
  return member is Procedure ? member.kind : null;
}

bool isNameVisibleIn(
    Name name, LibraryBuilder<KernelTypeBuilder, Library> library) {
  return !name.isPrivate || name.library == library.target;
}

class ClassHierarchyBuilder {
  final Map<KernelClassBuilder, ClassHierarchyNode> nodes =
      <KernelClassBuilder, ClassHierarchyNode>{};

  final KernelClassBuilder objectClass;

  bool hasNoSuchMethod = false;

  int abstractMemberCount = 0;

  ClassHierarchyBuilder(this.objectClass);

  Declaration handleOverride(KernelClassBuilder cls, Declaration member,
      Declaration superMember, MergeKind mergeKind) {
    if (member.next != null || superMember.next != null) {
      // Don't check overrides involving duplicated members.
      return member;
    }
    Member target = member.target;
    Member superTarget = superMember.target;
    if ((memberKind(target) ?? ProcedureKind.Getter) !=
        (memberKind(superTarget) ?? ProcedureKind.Getter)) {
      String name = member.fullNameForErrors;
      if (mergeKind == MergeKind.interfaces) {
        cls.addProblem(messageInheritedMembersConflict, cls.charOffset,
            cls.fullNameForErrors.length,
            context: <LocatedMessage>[
              messageInheritedMembersConflictCause1.withLocation(
                  member.fileUri, member.charOffset, name.length),
              messageInheritedMembersConflictCause2.withLocation(
                  superMember.fileUri, superMember.charOffset, name.length),
            ]);
      } else {
        cls.addProblem(messageDeclaredMemberConflictsWithInheritedMember,
            member.charOffset, name.length,
            context: <LocatedMessage>[
              messageDeclaredMemberConflictsWithInheritedMemberCause
                  .withLocation(
                      superMember.fileUri, superMember.charOffset, name.length)
            ]);
      }
    }
    if (target.name == noSuchMethodName && !target.isAbstract) {
      hasNoSuchMethod = true;
    }
    Declaration result = member;
    if (mergeKind == MergeKind.interfaces) {
      // TODO(ahe): Combine the signatures of member and superMember.
    } else if (target.isAbstract) {
      if (!superTarget.isAbstract) {
        // An abstract method doesn't override an implemention inherited from a
        // superclass.
        result = superMember;
      } else {
        abstractMemberCount++;
      }
    }
    return result;
  }

  void handleNewMember(Declaration member, MergeKind mergeKind) {
    Member target = member.target;
    if (mergeKind == MergeKind.superclass && target.isAbstract) {
      abstractMemberCount++;
    }
  }

  void handleInheritance(
      KernelClassBuilder cls, Declaration member, MergeKind mergeKind) {
    Member target = member.target;
    if (mergeKind == MergeKind.superclass && target.isAbstract) {
      if (isNameVisibleIn(target.name, cls.library)) {
        abstractMemberCount++;
      }
    }
    if (member.parent != objectClass &&
        target.name == noSuchMethodName &&
        !target.isAbstract) {
      hasNoSuchMethod = true;
    }
  }

  void add(KernelClassBuilder cls) {
    if (cls.isPatch) {
      // TODO(ahe): What about patch classes. Have we injected patched members
      // into the class-builder's scope?
      return;
    }
    ClassHierarchyNode supernode;
    if (objectClass != cls) {
      supernode = getNode(cls.supertype);
      if (supernode == null) {
        supernode = nodes[objectClass];
        if (supernode == null) {
          add(objectClass);
          supernode = nodes[objectClass];
        }
      }
      assert(supernode != null);
    }

    Scope scope = cls.scope;
    if (cls.isMixinApplication) {
      Declaration mixin = getDeclaration(cls.mixedInType);
      if (mixin is KernelClassBuilder) {
        scope = mixin.scope;
      }
    }
    List<Declaration> sortedLocals =
        new List<Declaration>.from(scope.local.values)
          ..sort(compareDeclarations);
    List<Declaration> sortedSetters =
        new List<Declaration>.from(scope.setters.values)
          ..sort(compareDeclarations);
    List<Declaration> allMembers;
    List<Declaration> allSetters;
    List<Declaration> interfaceMembers;
    List<Declaration> interfaceSetters;
    if (supernode == null) {
      // This should be Object.
      interfaceMembers = allMembers = sortedLocals;
      interfaceSetters = allSetters = sortedSetters;
    } else {
      allMembers = merge(
          cls, sortedLocals, supernode.classMembers, MergeKind.superclass);
      allSetters = merge(
          cls, sortedSetters, supernode.classSetters, MergeKind.superclass);
      List<KernelTypeBuilder> interfaces = cls.interfaces;
      if (interfaces != null) {
        MergeResult result = mergeInterfaces(cls, supernode, interfaces);
        interfaceMembers = result.mergedMembers;
        interfaceSetters = result.mergedSetters;
      } else {
        interfaceMembers = allMembers;
        interfaceSetters = allSetters;
      }
    }
    nodes[cls] = new ClassHierarchyNode(
        cls, scope, allMembers, allSetters, interfaceMembers, interfaceSetters);
    mergeAccessors(cls, allMembers, allSetters);

    if (abstractMemberCount != 0 && !cls.isAbstract) {
      if (!hasNoSuchMethod) {
        reportMissingMembers(cls, allMembers, allSetters);
      }
      installNsmHandlers(cls);
    }
    hasNoSuchMethod = false;
    abstractMemberCount = 0;
  }

  MergeResult mergeInterfaces(KernelClassBuilder cls,
      ClassHierarchyNode supernode, List<KernelTypeBuilder> interfaces) {
    List<List<Declaration>> memberLists =
        List<List<Declaration>>(interfaces.length + 1);
    List<List<Declaration>> setterLists =
        List<List<Declaration>>(interfaces.length + 1);
    memberLists[0] = supernode.interfaceMembers;
    setterLists[0] = supernode.interfaceSetters;
    for (int i = 0; i < interfaces.length; i++) {
      ClassHierarchyNode interfaceNode = getNode(interfaces[i]);
      if (interfaceNode == null) {
        memberLists[i + 1] = <Declaration>[];
        setterLists[i + 1] = <Declaration>[];
      } else {
        memberLists[i + 1] = interfaceNode.interfaceMembers;
        setterLists[i + 1] = interfaceNode.interfaceSetters;
      }
    }
    return new MergeResult(
        mergeLists(cls, memberLists), mergeLists(cls, setterLists));
  }

  List<Declaration> mergeLists(
      KernelClassBuilder cls, List<List<Declaration>> input) {
    // This is a k-way merge sort (where k is `interfaces.length + 1`). We
    // merge the lists pairwise, which reduces the number of lists to merge by
    // half on each iteration. Consequently, we perform O(log k) merges.
    while (input.length > 1) {
      List<List<Declaration>> output = <List<Declaration>>[];
      for (int i = 0; i < input.length - 1; i += 2) {
        output.add(merge(cls, input[i], input[i + 1], MergeKind.interfaces));
      }
      if (input.length.isOdd) {
        output.add(input.last);
      }
      input = output;
    }
    return input.single;
  }

  /// Merge [and check] accessors. This entails removing setters corresponding
  /// to fields, and checking that setters don't override regular methods.
  void mergeAccessors(KernelClassBuilder cls, List<Declaration> allMembers,
      List<Declaration> allSetters) {
    List<Declaration> overriddenSetters;
    int i = 0;
    int j = 0;
    while (i < allMembers.length && j < allSetters.length) {
      Declaration member = allMembers[i];
      Declaration setter = allSetters[j];
      final int compare = compareDeclarations(member, setter);
      if (compare == 0) {
        if (member.isField) {
          // TODO(ahe): What happens if we have both a field and a setter
          // declared in the same class?
          if (!member.isFinal && !member.isConst) {
            // The field overrides the setter.
            (overriddenSetters ??= <Declaration>[]).add(setter);
            Member target = setter.target;
            if (target.isAbstract) {
              abstractMemberCount--;
            }
          }
        } else if (!member.isGetter) {
          String name = member.fullNameForErrors;
          cls.library.addProblem(
              messageDeclaredMemberConflictsWithInheritedMember,
              member.charOffset,
              name.length,
              member.fileUri,
              context: <LocatedMessage>[
                messageDeclaredMemberConflictsWithInheritedMemberCause
                    .withLocation(
                        setter.fileUri, setter.charOffset, name.length)
              ]);
        }
        i++;
        j++;
      } else if (compare < 0) {
        i++;
      } else {
        j++;
      }
    }
    // One of of the two lists is now exhausted. What remains in the other list
    // cannot be a conflict.

    if (overriddenSetters != null) {
      // Remove [overriddenSetters] from [allSetters] by copying [allSetters]
      // to itself.
      int i = 0;
      int j = 0;
      int storeIndex = 0;
      while (i < allSetters.length && j < overriddenSetters.length) {
        if (allSetters[i] == overriddenSetters[j]) {
          i++;
          j++;
        } else {
          allSetters[storeIndex++] = allSetters[i++];
        }
      }
      while (i < allSetters.length) {
        allSetters[storeIndex++] = allSetters[i++];
      }
      allSetters.length = storeIndex;
    }
  }

  void reportMissingMembers(KernelClassBuilder cls,
      List<Declaration> allMembers, List<Declaration> allSetters) {
    List<LocatedMessage> context = <LocatedMessage>[];
    List<String> missingNames = <String>[];
    for (int j = 0; j < 2; j++) {
      List<Declaration> members = j == 0 ? allMembers : allSetters;
      for (int i = 0; i < members.length; i++) {
        Declaration declaration = members[i];
        Member target = declaration.target;
        if (target.isAbstract && isNameVisibleIn(target.name, cls.library)) {
          String name = declaration.fullNameForErrors;
          String parentName = declaration.parent.fullNameForErrors;
          String displayName =
              declaration.isSetter ? "$parentName.$name=" : "$parentName.$name";
          missingNames.add(displayName);
          context.add(templateMissingImplementationCause
              .withArguments(displayName)
              .withLocation(
                  declaration.fileUri, declaration.charOffset, name.length));
        }
      }
    }
    cls.addProblem(
        templateMissingImplementationNotAbstract.withArguments(
            cls.fullNameForErrors, missingNames),
        cls.charOffset,
        cls.fullNameForErrors.length,
        context: context);
  }

  void installNsmHandlers(KernelClassBuilder cls) {
    // TOOD(ahe): Implement this.
  }

  ClassHierarchyNode getNode(KernelTypeBuilder type) {
    if (type is KernelNamedTypeBuilder) {
      Declaration declaration = type.declaration;
      if (declaration is KernelClassBuilder) {
        ClassHierarchyNode node = nodes[declaration];
        if (node == null && declaration is KernelClassBuilder) {
          add(declaration);
          node = nodes[declaration];
        }
        return node;
      }
    }
    return null;
  }

  Declaration getDeclaration(KernelTypeBuilder type) {
    return type is KernelNamedTypeBuilder ? type.declaration : null;
  }

  List<Declaration> merge(
      KernelClassBuilder cls,
      List<Declaration> localMembers,
      List<Declaration> superMembers,
      MergeKind mergeKind) {
    final List<Declaration> mergedMembers = new List<Declaration>.filled(
        localMembers.length + superMembers.length, null,
        growable: true);

    int mergedMemberCount = 0;

    int i = 0;
    int j = 0;
    while (i < localMembers.length && j < superMembers.length) {
      final Declaration localMember = localMembers[i];
      final Declaration superMember = superMembers[j];
      final int compare = compareDeclarations(localMember, superMember);
      if (compare == 0) {
        mergedMembers[mergedMemberCount++] =
            handleOverride(cls, localMember, superMember, mergeKind);
        i++;
        j++;
      } else if (compare < 0) {
        handleNewMember(localMember, mergeKind);
        mergedMembers[mergedMemberCount++] = localMember;
        i++;
      } else {
        handleInheritance(cls, superMember, mergeKind);
        mergedMembers[mergedMemberCount++] = superMember;
        j++;
      }
    }
    while (i < localMembers.length) {
      final Declaration localMember = localMembers[i];
      handleNewMember(localMember, mergeKind);
      mergedMembers[mergedMemberCount++] = localMember;
      i++;
    }
    while (j < superMembers.length) {
      final Declaration superMember = superMembers[j];
      handleInheritance(cls, superMember, mergeKind);
      mergedMembers[mergedMemberCount++] = superMember;
      j++;
    }
    return mergedMembers..length = mergedMemberCount;
  }
}

class ClassHierarchyNode {
  /// The class corresponding to this hierarchy node.
  final KernelClassBuilder cls;

  /// The local members of [cls]. For regular classes, this is simply
  /// `cls.scope`, but for mixin-applications this is the mixed-in type's
  /// scope. The members are sorted in order of declaration.
  // TODO(ahe): Do we need to copy the scope from the mixed-in type to remove
  // static members?
  final Scope localMembers;

  /// All the members of this class including [classMembers] of its
  /// superclasses. The members are sorted by [compareDeclarations].
  final List<Declaration> classMembers;

  /// Similar to [classMembers] but for setters.
  final List<Declaration> classSetters;

  /// All the interface members of this class including [interfaceMembers] of
  /// its supertypes. The members are sorted by [compareDeclarations].
  ///
  /// In addition to the members of [classMembers] this also contains members
  /// from interfaces.
  final List<Declaration> interfaceMembers;

  /// Similar to [interfaceMembers] but for setters.
  final List<Declaration> interfaceSetters;

  ClassHierarchyNode(this.cls, this.localMembers, this.classMembers,
      this.classSetters, this.interfaceMembers, this.interfaceSetters);
}

class MergeResult {
  final List<Declaration> mergedMembers;

  final List<Declaration> mergedSetters;

  MergeResult(this.mergedMembers, this.mergedSetters);
}

enum MergeKind {
  /// Merging superclass members with the current class.
  superclass,

  /// Merging two interfaces.
  interfaces,

  /// Merging class members with interface members.
  supertypes,
}
