// Copyright (c) 2019, 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/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/error/codes.dart';

/// Verifier for initializing fields in constructors.
class ConstructorFieldsVerifier {
  final TypeSystemImpl _typeSystem;
  final ErrorReporter _errorReporter;

  bool _isInNativeClass = false;

  /// When a new class or mixin is entered, [_initFieldsMap] initializes this
  /// map, and [leaveClassOrMixin] resets it.
  ///
  /// [_InitState.notInit] or [_InitState.initInDeclaration] is set for each
  /// field. Later [verify] is called to verify each constructor of the class.
  Map<FieldElement, _InitState>? _initialFieldMap;

  /// The state of fields in the current constructor.
  Map<FieldElement, _InitState> _fieldMap = {};

  /// Set to `true` if the current constructor redirects.
  bool _hasRedirectingConstructorInvocation = false;

  ConstructorFieldsVerifier({
    required TypeSystemImpl typeSystem,
    required ErrorReporter errorReporter,
  })   : _typeSystem = typeSystem,
        _errorReporter = errorReporter;

  void enterClass(ClassDeclaration node) {
    _isInNativeClass = node.nativeClause != null;
    _initFieldsMap(node.declaredElement!);
  }

  void leaveClass() {
    _isInNativeClass = false;
    _initialFieldMap = null;
  }

  /// Verify that the given [node] declaration does not violate any of
  /// the error codes relating to the initialization of fields in the
  /// enclosing class.
  void verify(ConstructorDeclaration node) {
    if (node.factoryKeyword != null ||
        node.redirectedConstructor != null ||
        node.externalKeyword != null) {
      return;
    }

    if (node.parent is! ClassDeclaration) {
      return;
    }

    if (_isInNativeClass) {
      return;
    }

    _fieldMap = Map.of(_initialFieldMap!);
    _hasRedirectingConstructorInvocation = false;

    _updateWithParameters(node);
    _updateWithInitializers(node);

    if (_hasRedirectingConstructorInvocation) {
      return;
    }

    // Prepare lists of not initialized fields.
    List<FieldElement> notInitFinalFields = <FieldElement>[];
    List<FieldElement> notInitNonNullableFields = <FieldElement>[];
    _fieldMap.forEach((FieldElement field, _InitState state) {
      if (state != _InitState.notInit) return;
      if (field.isLate) return;
      if (field.isAbstract || field.isExternal) return;

      if (field.isFinal) {
        notInitFinalFields.add(field);
      } else if (_typeSystem.isNonNullableByDefault &&
          _typeSystem.isPotentiallyNonNullable(field.type)) {
        notInitNonNullableFields.add(field);
      }
    });

    _reportNotInitializedFinal(node, notInitFinalFields);
    _reportNotInitializedNonNullable(node, notInitNonNullableFields);
  }

  void _initFieldsMap(ClassElement element) {
    _initialFieldMap = <FieldElement, _InitState>{};
    for (var field in element.fields) {
      if (!field.isSynthetic) {
        _initialFieldMap![field] = field.hasInitializer
            ? _InitState.initInDeclaration
            : _InitState.notInit;
      }
    }
  }

  void _reportNotInitializedFinal(
    ConstructorDeclaration node,
    List<FieldElement> notInitFinalFields,
  ) {
    if (notInitFinalFields.isEmpty) {
      return;
    }

    var names = notInitFinalFields.map((item) => item.name).toList();
    names.sort();

    if (names.length == 1) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1,
        node.returnType,
        names,
      );
    } else if (names.length == 2) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2,
        node.returnType,
        names,
      );
    } else {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS,
        node.returnType,
        [names[0], names[1], names.length - 2],
      );
    }
  }

  void _reportNotInitializedNonNullable(
    ConstructorDeclaration node,
    List<FieldElement> notInitNonNullableFields,
  ) {
    if (notInitNonNullableFields.isEmpty) {
      return;
    }

    var names = notInitNonNullableFields.map((f) => f.name).toList();
    names.sort();

    for (var name in names) {
      _errorReporter.reportErrorForNode(
        CompileTimeErrorCode
            .NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR,
        node.returnType,
        [name],
      );
    }
  }

  void _updateWithInitializers(ConstructorDeclaration node) {
    for (var initializer in node.initializers) {
      if (initializer is RedirectingConstructorInvocation) {
        _hasRedirectingConstructorInvocation = true;
      }
      if (initializer is ConstructorFieldInitializer) {
        SimpleIdentifier fieldName = initializer.fieldName;
        var element = fieldName.staticElement;
        if (element is FieldElement) {
          var state = _fieldMap[element];
          if (state == _InitState.notInit) {
            _fieldMap[element] = _InitState.initInInitializer;
          } else if (state == _InitState.initInDeclaration) {
            if (element.isFinal || element.isConst) {
              _errorReporter.reportErrorForNode(
                CompileTimeErrorCode
                    .FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION,
                fieldName,
              );
            }
          } else if (state == _InitState.initInFieldFormal) {
            _errorReporter.reportErrorForNode(
              CompileTimeErrorCode
                  .FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER,
              fieldName,
            );
          } else if (state == _InitState.initInInitializer) {
            _errorReporter.reportErrorForNode(
              CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS,
              fieldName,
              [element.displayName],
            );
          }
        }
      }
    }
  }

  void _updateWithParameters(ConstructorDeclaration node) {
    var formalParameters = node.parameters.parameters;
    for (FormalParameter parameter in formalParameters) {
      parameter = _baseParameter(parameter);
      if (parameter is FieldFormalParameter) {
        var fieldElement =
            (parameter.declaredElement as FieldFormalParameterElementImpl)
                .field;
        if (fieldElement == null) {
          continue;
        }
        _InitState? state = _fieldMap[fieldElement];
        if (state == _InitState.notInit) {
          _fieldMap[fieldElement] = _InitState.initInFieldFormal;
        } else if (state == _InitState.initInDeclaration) {
          if (fieldElement.isFinal || fieldElement.isConst) {
            _errorReporter.reportErrorForNode(
              CompileTimeErrorCode
                  .FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR,
              parameter.identifier,
              [fieldElement.displayName],
            );
          }
        } else if (state == _InitState.initInFieldFormal) {
          // Reported in DuplicateDefinitionVerifier._checkDuplicateIdentifier
        }
      }
    }
  }

  static FormalParameter _baseParameter(FormalParameter parameter) {
    if (parameter is DefaultFormalParameter) {
      return parameter.parameter;
    }
    return parameter;
  }
}

/// The four states of a field initialization state through a constructor
/// signature, not initialized, initialized in the field declaration,
/// initialized in the field formal, and finally, initialized in the
/// initializers list.
enum _InitState {
  /// The field is declared without an initializer.
  notInit,

  /// The field is declared with an initializer.
  initInDeclaration,

  /// The field is initialized in a field formal parameter of the constructor
  /// being verified.
  initInFieldFormal,

  /// The field is initialized in the list of initializers of the constructor
  /// being verified.
  initInInitializer,
}
