// 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:_fe_analyzer_shared/src/scanner/characters.dart';
import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/src/services/correction/fix/pubspec/fix_kind.dart';
import 'package:analysis_server/src/utilities/yaml_node_locator.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/pubspec/pubspec_warning_code.dart';
import 'package:analyzer/src/util/yaml.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:yaml/yaml.dart';

/// The generator used to generate fixes in pubspec.yaml files.
class PubspecFixGenerator {
  /// The resource provider used to access the file system.
  final ResourceProvider resourceProvider;

  /// The error for which fixes are being generated.
  final AnalysisError error;

  /// The offset of the [error] for which fixes are being generated.
  final int errorOffset;

  /// The length of the [error] for which fixes are being generated.
  final int errorLength;

  /// The textual content of the file for which fixes are being generated.
  final String content;

  /// The parsed content of the file for which fixes are being generated.
  final YamlDocument document;

  final LineInfo lineInfo;

  /// The fixes that were generated.
  final List<Fix> fixes = <Fix>[];

  /// The end-of-line marker used in the `pubspec.yaml` file.
  String? _endOfLine;

  PubspecFixGenerator(
      this.resourceProvider, this.error, this.content, this.document)
      : errorOffset = error.offset,
        errorLength = error.length,
        lineInfo = LineInfo.fromContent(content);

  /// Returns the end-of-line marker to use for the `pubspec.yaml` file.
  String get endOfLine {
    // TODO(brianwilkerson) Share this with CorrectionUtils, probably by
    //  creating a subclass of CorrectionUtils containing utilities that are
    //  only dependent on knowing the content of the file. Also consider moving
    //  this kind of utility into the ChangeBuilder API directly.
    var endOfLine = _endOfLine;
    if (endOfLine != null) {
      return endOfLine;
    }

    if (content.contains('\r\n')) {
      return _endOfLine = '\r\n';
    } else {
      return _endOfLine = '\n';
    }
  }

  /// Return the absolute, normalized path to the file in which the error was
  /// reported.
  String get file => error.source.fullName;

  /// Return the list of fixes that apply to the error being fixed.
  Future<List<Fix>> computeFixes() async {
    var locator =
        YamlNodeLocator(start: errorOffset, end: errorOffset + errorLength - 1);
    var coveringNodePath = locator.searchWithin(document.contents);
    if (coveringNodePath.isEmpty) {
      // One of the errors doesn't have a covering path but can still be fixed.
      // The `if` was left so that the variable wouldn't be unused.
      // return fixes;
    }

    var errorCode = error.errorCode;
    if (errorCode == PubspecWarningCode.ASSET_DOES_NOT_EXIST) {
      // Consider replacing the path with a valid path.
    } else if (errorCode == PubspecWarningCode.ASSET_DIRECTORY_DOES_NOT_EXIST) {
      // Consider replacing the path with a valid path.
      // Consider creating the directory.
    } else if (errorCode == PubspecWarningCode.ASSET_FIELD_NOT_LIST) {
      // Not sure how to fix a structural issue.
    } else if (errorCode == PubspecWarningCode.ASSET_NOT_STRING) {
      // Not sure how to fix a structural issue.
    } else if (errorCode == PubspecWarningCode.DEPENDENCIES_FIELD_NOT_MAP) {
      // Not sure how to fix a structural issue.
    } else if (errorCode == PubspecWarningCode.DEPRECATED_FIELD) {
      // Consider removing the field.
    } else if (errorCode == PubspecWarningCode.FLUTTER_FIELD_NOT_MAP) {
      // Not sure how to fix a structural issue.
    } else if (errorCode == PubspecWarningCode.INVALID_DEPENDENCY) {
      // Consider adding `publish_to: none`.
    } else if (errorCode == PubspecWarningCode.MISSING_NAME) {
      await _addNameEntry();
    } else if (errorCode == PubspecWarningCode.NAME_NOT_STRING) {
      // Not sure how to fix a structural issue.
    } else if (errorCode == PubspecWarningCode.PATH_DOES_NOT_EXIST) {
      // Consider replacing the path with a valid path.
    } else if (errorCode == PubspecWarningCode.PATH_NOT_POSIX) {
      // Consider converting to a POSIX-style path.
    } else if (errorCode == PubspecWarningCode.PATH_PUBSPEC_DOES_NOT_EXIST) {
      // Consider replacing the path with a valid path.
    } else if (errorCode == PubspecWarningCode.UNNECESSARY_DEV_DEPENDENCY) {
      // Consider removing the dependency.
    }
    return fixes;
  }

  /// Add a fix whose edits were built by the [builder] that has the given
  /// [kind]. If [args] are provided, they will be used to fill in the message
  /// for the fix.
  // ignore: unused_element
  void _addFixFromBuilder(ChangeBuilder builder, FixKind kind, {List? args}) {
    var change = builder.sourceChange;
    if (change.edits.isEmpty) {
      return;
    }
    change.id = kind.id;
    change.message = formatList(kind.message, args);
    fixes.add(Fix(kind, change));
  }

  Future<void> _addNameEntry() async {
    var context = resourceProvider.pathContext;
    var packageName = _identifierFrom(context.basename(context.dirname(file)));
    var builder = ChangeBuilder(
        workspace: _NonDartChangeWorkspace(resourceProvider), eol: endOfLine);
    var firstOffset = _initialOffset(document.contents);
    if (firstOffset < 0) {
      // The document contains a list, and we don't support converting it to a
      // map.
      return;
    }
    await builder.addGenericFileEdit(file, (builder) {
      // TODO(brianwilkerson) Generalize this to add a key to any map by
      //  inserting the indentation of the line containing `firstOffset` after
      //  the end-of-line marker.
      builder.addSimpleInsertion(firstOffset, 'name: $packageName$endOfLine');
    });
    _addFixFromBuilder(builder, PubspecFixKind.addName);
  }

  String _identifierFrom(String directoryName) {
    var buffer = StringBuffer();
    for (var i = 0; i < directoryName.length; i++) {
      var currentChar = directoryName[i];
      if (_isIdentifierChar(currentChar.codeUnitAt(0))) {
        buffer.write(currentChar.toLowerCase());
      }
    }
    if (buffer.isEmpty) {
      return 'insertNameHere';
    }
    return buffer.toString();
  }

  int _initialOffset(YamlNode node) {
    if (node is YamlMap) {
      return _offsetOfFirstKey(node);
    } else if (node is YamlScalar) {
      return node.span.start.offset;
    }
    return -1;
  }

  bool _isIdentifierChar(int next) {
    return ($a <= next && next <= $z) ||
        ($A <= next && next <= $Z) ||
        ($0 <= next && next <= $9) ||
        identical(next, $_);
  }

  int _offsetOfFirstKey(YamlMap map) {
    var firstOffset = -1;
    for (var key in map.nodeMap.keys) {
      var keyOffset = key.span.start.offset;
      if (firstOffset < 0 || keyOffset < firstOffset) {
        firstOffset = keyOffset;
      }
    }
    if (firstOffset < 0) {
      firstOffset = 0;
    }
    return firstOffset;
  }
}

class _NonDartChangeWorkspace implements ChangeWorkspace {
  @override
  ResourceProvider resourceProvider;

  _NonDartChangeWorkspace(this.resourceProvider);

  @override
  bool containsFile(String path) {
    return true;
  }

  @override
  AnalysisSession getSession(String path) {
    throw UnimplementedError('Attempt to work a Dart file.');
  }
}
