// Copyright (c) 2021, 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/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.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_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';

class AddMissingEnumLikeCaseClauses extends CorrectionProducer {
  @override
  FixKind get fixKind => DartFixKind.ADD_MISSING_ENUM_CASE_CLAUSES;

  // TODO: Consider enabling this lint for fix all in file.
  // @override
  // FixKind? get multiFixKind => super.multiFixKind;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    final node = this.node;
    if (node is SwitchStatement) {
      var expressionType = node.expression.staticType;
      if (expressionType is! InterfaceType) {
        return;
      }
      var classElement = expressionType.element;
      var className = classElement.name;
      var caseNames = _caseNames(node);
      var missingNames = _constantNames(classElement)
        ..removeWhere((e) => caseNames.contains(e));
      missingNames.sort();

      var statementIndent = utils.getLinePrefix(node.offset);
      var singleIndent = utils.getIndent(1);
      var location = utils.newCaseClauseAtEndLocation(node);

      await builder.addDartFileEdit(file, (builder) {
        // TODO(brianwilkerson) Consider inserting the names in order into the
        //  switch statement.
        builder.addInsertion(location.offset, (builder) {
          builder.write(location.prefix);
          for (var name in missingNames) {
            builder.write(statementIndent);
            builder.write(singleIndent);
            builder.write('case ');
            builder.write(className);
            builder.write('.');
            builder.write(name);
            builder.writeln(':');
            builder.write(statementIndent);
            builder.write(singleIndent);
            builder.write(singleIndent);
            builder.writeln('// TODO: Handle this case.');
            builder.write(statementIndent);
            builder.write(singleIndent);
            builder.write(singleIndent);
            builder.writeln('break;');
          }
          builder.write(location.suffix);
        });
      });
    }
  }

  /// Return the names of the constants already in a case clause in the
  /// [statement].
  List<String> _caseNames(SwitchStatement statement) {
    var caseNames = <String>[];
    for (var member in statement.members) {
      if (member is SwitchCase) {
        var expression = member.expression;
        if (expression is Identifier) {
          var element = expression.staticElement;
          if (element is PropertyAccessorElement) {
            caseNames.add(element.name);
          }
        } else if (expression is PropertyAccess) {
          caseNames.add(expression.propertyName.name);
        }
      }
    }
    return caseNames;
  }

  /// Return the names of the constants defined in [classElement].
  List<String> _constantNames(ClassElement classElement) {
    var type = classElement.thisType;
    var constantNames = <String>[];
    for (var field in classElement.fields) {
      // Ensure static const.
      if (field.isSynthetic || !field.isConst || !field.isStatic) {
        continue;
      }
      // Check for type equality.
      if (field.type != type) {
        continue;
      }
      constantNames.add(field.name);
    }
    return constantNames;
  }
}
