// 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_collection.dart';
import 'package:analyzer/dart/analysis/analysis_context.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:analyzer/dart/ast/visitor.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 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 (CompilationUnitMember unitMember in result.unit.declarations) {
    if (unitMember is ClassDeclaration && unitMember.name.name == className) {
      for (ClassMember classMember in unitMember.members) {
        if (classMember is FieldDeclaration) {
          for (VariableDeclaration field in classMember.fields.variables) {
            final String fieldName = field.name.name;
            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,
}) {
  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 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 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,
}) {
  List<String> values = <String>[];
  for (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) {
  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 (PartDirective part in uiResult.unit.directives.whereType<PartDirective>()) {
    final String partPath = part.uri.stringValue!;
    final ParseStringResult partResult = parseFile(path: '$uiRoot/$partPath', featureSet: analyzerFeatures);

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