// Copyright (c) 2015, 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 domains.analysis.implemented_dart;

import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/element/element.dart';

class ImplementedComputer {
  final SearchEngine searchEngine;
  final CompilationUnitElement unitElement;

  List<protocol.ImplementedClass> classes = <protocol.ImplementedClass>[];
  List<protocol.ImplementedMember> members = <protocol.ImplementedMember>[];

  Set<ClassElement> subtypes;

  ImplementedComputer(this.searchEngine, this.unitElement);

  compute() async {
    for (ClassElement type in unitElement.types) {
      // always include Object and its members
      if (type.supertype == null) {
        _addImplementedClass(type);
        type.accessors.forEach(_addImplementedMember);
        type.fields.forEach(_addImplementedMember);
        type.methods.forEach(_addImplementedMember);
        continue;
      }
      // analyze ancestors
      subtypes = await searchEngine.searchAllSubtypes(type);
      if (subtypes.isNotEmpty) {
        _addImplementedClass(type);
      }
      type.accessors.forEach(_addMemberIfImplemented);
      type.fields.forEach(_addMemberIfImplemented);
      type.methods.forEach(_addMemberIfImplemented);
    }
  }

  void _addImplementedClass(ClassElement type) {
    int offset = type.nameOffset;
    int length = type.nameLength;
    classes.add(new protocol.ImplementedClass(offset, length));
  }

  void _addImplementedMember(Element member) {
    int offset = member.nameOffset;
    int length = member.nameLength;
    members.add(new protocol.ImplementedMember(offset, length));
  }

  void _addMemberIfImplemented(Element element) {
    if (element.isSynthetic || _isStatic(element)) {
      return;
    }
    if (_hasOverride(element)) {
      _addImplementedMember(element);
    }
  }

  bool _hasOverride(Element element) {
    String name = element.displayName;
    LibraryElement library = element.library;
    for (ClassElement subtype in subtypes) {
      ClassMemberElement subElement = subtype.getMethod(name);
      if (subElement == null) {
        subElement = subtype.getField(name);
      }
      if (subElement != null &&
          !subElement.isStatic &&
          subElement.isAccessibleIn(library)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Return `true` if the given [element] is a static element.
   */
  static bool _isStatic(Element element) {
    if (element is ExecutableElement) {
      return element.isStatic;
    } else if (element is PropertyInducingElement) {
      return element.isStatic;
    }
    return false;
  }
}
