// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:convert' show LineSplitter;
import 'dart:io';

import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:pub_semver/pub_semver.dart';

/// Returns all indexed fields in [className].
///
/// Field names are expected to be of the form `kFooBarIndex`; prefixed with a
/// `k` and terminated in `Index`.
List<String> getDartClassFields({
  required String sourcePath,
  required String className,
}) {
  final List<String> includedPaths = <String>[sourcePath];
  final AnalysisContextCollection collection = AnalysisContextCollection(includedPaths: includedPaths);
  final AnalysisContext context = collection.contextFor(sourcePath);
  final AnalysisSession session = context.currentSession;

  final SomeParsedUnitResult result = session.getParsedUnit(sourcePath);
  if (result is! ParsedUnitResult) {
    return <String>[];
  }

  // Locate all fields matching the expression in the class.
  final RegExp fieldExp = RegExp(r'_k(\w*)Index');
  final List<String> fields = <String>[];
  for (final CompilationUnitMember unitMember in result.unit.declarations) {
    if (unitMember is ClassDeclaration && unitMember.name2.lexeme == className) {
      for (final ClassMember classMember in unitMember.members) {
        if (classMember is FieldDeclaration) {
          for (final VariableDeclaration field in classMember.fields.variables) {
            final String fieldName = field.name2.lexeme;
            final RegExpMatch? match = fieldExp.firstMatch(fieldName);
            if (match != null) {
              fields.add(match.group(1)!);
            }
          }
        }
      }
    }
  }
  return fields;
}

/// Returns all values in [enumName].
///
/// Enum values are expected to be of the form `kEnumNameFooBar`; prefixed with
/// `kEnumName`.
List<String> getCppEnumValues({
  required String sourcePath,
  required String enumName,
}) {
  final List<String> lines = File(sourcePath).readAsLinesSync();
  final int enumEnd = lines.indexOf('} $enumName;');
  if (enumEnd < 0) {
    return <String>[];
  }
  final int enumStart = lines.lastIndexOf('typedef enum {', enumEnd);
  if (enumStart < 0 || enumStart >= enumEnd) {
    return <String>[];
  }
  final RegExp valueExp = RegExp('^\\s*k$enumName(\\w*)');
  return _extractMatchingExpression(
    lines: lines.sublist(enumStart + 1, enumEnd),
    regexp: valueExp,
  );
}

/// Returns all values in [enumName].
///
/// Enum values are expected to be of the form `kFooBar`; prefixed with `k`.
List<String> getCppEnumClassValues({
  required String sourcePath,
  required String enumName,
}) {
  final List<String> lines = _getBlockStartingWith(
    source: File(sourcePath).readAsStringSync(),
    startExp: RegExp('enum class $enumName .* {'),
  );
  final RegExp valueExp = RegExp(r'^\s*k(\w*)');
  return _extractMatchingExpression(lines: lines, regexp: valueExp);
}

/// Returns all values in [enumName].
///
/// Enum value declarations are expected to be of the form `FOO_BAR(1 << N)`;
/// in all caps.
List<String> getJavaEnumValues({
  required String sourcePath,
  required String enumName,
}) {
  final List<String> lines = _getBlockStartingWith(
    source: File(sourcePath).readAsStringSync(),
    startExp: RegExp('enum $enumName {'),
  );
  final RegExp valueExp = RegExp(r'^\s*([A-Z_]*)\(');
  return _extractMatchingExpression(lines: lines, regexp: valueExp);
}

/// Returns all values in [lines] whose line of code matches [regexp].
///
/// The contents of the first match group in [regexp] is returned; therefore
/// it must contain a match group.
List<String> _extractMatchingExpression({
  required Iterable<String> lines,
  required RegExp regexp,
}) {
  final List<String> values = <String>[];
  for (final String line in lines) {
    final RegExpMatch? match = regexp.firstMatch(line);
    if (match != null) {
      values.add(match.group(1)!);
    }
  }
  return values;
}

/// Returns all lines of the block starting with [startString].
///
/// [startString] MUST end with '{'.
List<String> _getBlockStartingWith({
  required String source,
  required RegExp startExp,
}) {
  assert(startExp.pattern.endsWith('{'));

  final int blockStart = source.indexOf(startExp);
  if (blockStart < 0) {
    return <String>[];
  }
  // Find start of block.
  int pos = blockStart;
  while (pos < source.length && source[pos] != '{') {
    pos++;
  }
  int braceCount = 1;

  // Count braces until end of block.
  pos++;
  while (pos < source.length && braceCount > 0) {
    if (source[pos] == '{') {
      braceCount++;
    } else if (source[pos] == '}') {
      braceCount--;
    }
    pos++;
  }
  final int blockEnd = pos;
  return LineSplitter.split(source, blockStart, blockEnd).toList();
}

/// Apply a visitor to all compilation units in the dart:ui library.
void visitUIUnits(String flutterRoot, AstVisitor<void> visitor) {
  final String uiRoot = '$flutterRoot/lib/ui';
  final FeatureSet analyzerFeatures = FeatureSet.fromEnableFlags2(
    sdkLanguageVersion: Version.parse('2.17.0'),
    flags: <String>['non-nullable'],
  );
  final ParseStringResult uiResult = parseFile(path: '$uiRoot/ui.dart', featureSet: analyzerFeatures);
  for (final PartDirective part in uiResult.unit.directives.whereType<PartDirective>()) {
    final String partPath = part.uri.stringValue!;
    final ParseStringResult partResult = parseFile(path: '$uiRoot/$partPath', featureSet: analyzerFeatures);

    for (final CompilationUnitMember unitMember in partResult.unit.declarations) {
      unitMember.accept(visitor);
    }
  }
}
