// 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.name.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.name.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);
    }
  }
}
