// Copyright (c) 2020, 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:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart' show ClassElement;
import 'package:analyzer/dart/element/type.dart';
import 'package:meta/meta.dart';

/// The path to an element.
class ElementDescriptor {
  /// The URIs of the library in which the element is defined.
  final List<Uri> libraryUris;

  /// The kind of element that was changed.
  final ElementKind kind;

  /// The components that uniquely identify the element within its library. The
  /// components are ordered from the most local to the most global.
  final List<String> components;

  /// Initialize a newly created element descriptor to describe an element
  /// accessible via any of the [libraryUris] where the path to the element
  /// within the library is given by the list of [components]. The [kind] of the
  /// element is represented by the key used in the data file.
  ElementDescriptor(
      {@required this.libraryUris,
      @required this.kind,
      @required this.components});

  /// Return `true` if the described element is a constructor.
  bool get isConstructor => kind == ElementKind.constructorKind;

  /// Return `true` if the given [node] appears to be consistent with this kind
  /// of element.
  bool matches(AstNode node) {
    // TODO(brianwilkerson) Check the resolved element if one exists for more
    //  accurate results.
    switch (kind) {
      case ElementKind.classKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.constantKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.constructorKind:
        if (node is Annotation) {
          var className = _nameFromIdentifier(node.name);
          var constructorName = node.constructorName ?? '';
          if (components[0] == constructorName && components[1] == className) {
            return true;
          }
        } else if (node is InstanceCreationExpression) {
          var name = node.constructorName;
          var className = _nameFromIdentifier(name.type.name);
          var constructorName = name.name?.name ?? '';
          if (components[0] == constructorName && components[1] == className) {
            return true;
          }
        } else if (node is MethodInvocation) {
          var target = node.target;
          if (target == null) {
            if (components[0] == '' && components[1] == node.methodName.name) {
              return true;
            }
          } else if (target is Identifier) {
            var className = _nameFromIdentifier(target);
            var constructorName = node.methodName.name;
            if (components[0] == constructorName &&
                components[1] == className) {
              return true;
            }
          }
        }
        return false;
      case ElementKind.enumKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.extensionKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.fieldKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.functionKind:
        if (node is MethodInvocation) {
          if (node.realTarget == null &&
              components[0] == node.methodName.name) {
            return true;
          }
        }
        return false;
      case ElementKind.getterKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.methodKind:
        if (node is MethodInvocation) {
          if (components[0] == node.methodName.name) {
            var target = node.realTarget;
            if (target == null) {
              // TODO(brianwilkerson) If `node.target == null` then the invocation
              //  should be in a subclass of the element's class.
              return true;
            } else {
              var type = target.staticType;
              if (type == null && target is SimpleIdentifier) {
                var element = target.staticElement;
                // TODO(brianwilkerson) Handle more than `ClassElement`.
                if (element is ClassElement) {
                  type = element.thisType;
                }
              }
              if (type == null) {
                // We can't get more specific type information, so we assume
                // that the method might have been in the element's class.
                return true;
              }
              if (components[1] == type.element.name) {
                return true;
              }
              if (type is InterfaceType) {
                for (var supertype in type.allSupertypes) {
                  if (components[1] == supertype.element.name) {
                    return true;
                  }
                }
              }
            }
          }
        }
        return false;
      case ElementKind.mixinKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.setterKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.typedefKind:
        // TODO: Handle this case.
        return false;
      case ElementKind.variableKind:
        // TODO: Handle this case.
        return false;
    }
    return false;
  }

  String _nameFromIdentifier(Identifier identifier) {
    if (identifier is SimpleIdentifier) {
      return identifier.name;
    } else if (identifier is PrefixedIdentifier) {
      return identifier.identifier.name;
    }
    throw StateError(
        'Unexpected class of identifier: ${identifier.runtimeType}');
  }
}
