// 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.

// ignore_for_file: avoid_print

import 'dart:io';

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

// Ignore members defined on Object.
const Set<String> _kObjectMembers = <String>{
  '==',
  'toString',
  'hashCode',
};

CompilationUnit _parseAndCheckDart(String path) {
  final FeatureSet analyzerFeatures = FeatureSet.fromEnableFlags2(
    flags: <String>['class-modifiers', 'sealed-class', 'records', 'patterns'],
    sdkLanguageVersion: Version.parse('3.0.0-0'),
  );
  if (!analyzerFeatures.isEnabled(Feature.non_nullable)) {
    throw Exception('non-nullable feature is disabled.');
  }
  final ParseStringResult result = parseFile(path: path, featureSet: analyzerFeatures, throwIfDiagnostics: false);
  if (result.errors.isNotEmpty) {
    result.errors.forEach(stderr.writeln);
    stderr.writeln('Failure!');
    exit(1);
  }
  return result.unit;
}

void main() {
  final String flutterDir = Platform.environment['FLUTTER_DIR']!;
  // These files just contain imports to the part files;
  final CompilationUnit uiUnit = _parseAndCheckDart('$flutterDir/lib/ui/ui.dart');
  final CompilationUnit webUnit = _parseAndCheckDart('$flutterDir/lib/web_ui/lib/ui.dart');
  final Map<String, ClassDeclaration> uiClasses = <String, ClassDeclaration>{};
  final Map<String, ClassDeclaration> webClasses = <String, ClassDeclaration>{};

  final Map<String, GenericTypeAlias> uiTypeDefs = <String, GenericTypeAlias>{};
  final Map<String, GenericTypeAlias> webTypeDefs = <String, GenericTypeAlias>{};

  // Gather all public classes from each library. For now we are skipping
  // other top level members.
  _collectPublicClasses(uiUnit, uiClasses, '$flutterDir/lib/ui/');
  _collectPublicClasses(webUnit, webClasses, '$flutterDir/lib/web_ui/lib/');

  _collectPublicTypeDefs(uiUnit, uiTypeDefs, '$flutterDir/lib/ui/');
  _collectPublicTypeDefs(webUnit, webTypeDefs, '$flutterDir/lib/web_ui/lib/');

  if (uiClasses.isEmpty || webClasses.isEmpty) {
    print('Warning: did not resolve any classes.');
  }

  if (uiTypeDefs.isEmpty || webTypeDefs.isEmpty) {
    print('Warning: did not resolve any typedefs.');
  }

  bool failed = false;
  print('Checking ${uiClasses.length} public classes.');
  for (final String className in uiClasses.keys) {
    final ClassDeclaration uiClass = uiClasses[className]!;
    final ClassDeclaration? webClass = webClasses[className];
    // If the web class is missing there isn't much left to do here. Print a
    // warning and move along.
    if (webClass == null) {
      failed = true;
      print('Warning: lib/ui/ui.dart contained public class $className, but '
          'this was missing from lib/web_ui/ui.dart.');
      continue;
    }
    // Next will check that the public methods exposed in each library are
    // identical.
    final Map<String, MethodDeclaration> uiMethods =
        <String, MethodDeclaration>{};
    final Map<String, MethodDeclaration> webMethods =
        <String, MethodDeclaration>{};
    final Map<String, ConstructorDeclaration> uiConstructors =
        <String, ConstructorDeclaration>{};
    final Map<String, ConstructorDeclaration> webConstructors =
        <String, ConstructorDeclaration>{};
    _collectPublicMethods(uiClass, uiMethods);
    _collectPublicMethods(webClass, webMethods);
    _collectPublicConstructors(uiClass, uiConstructors);
    _collectPublicConstructors(webClass, webConstructors);

    for (final String name in uiConstructors.keys) {
      final ConstructorDeclaration uiConstructor = uiConstructors[name]!;
      final ConstructorDeclaration? webConstructor = webConstructors[name];
      if (webConstructor == null) {
        failed = true;
        print(
          'Warning: lib/ui/ui.dart $className.$name is missing from lib/web_ui/ui.dart.',
        );
        continue;
      }

      if (uiConstructor.parameters.parameters.length !=
          webConstructor.parameters.parameters.length) {
        failed = true;
        print(
            'Warning: lib/ui/ui.dart $className.$name has a different parameter '
            'length than in lib/web_ui/ui.dart.');
      }

      for (int i = 0;
          i < uiConstructor.parameters.parameters.length &&
              i < uiConstructor.parameters.parameters.length;
          i++) {
        // Technically you could re-order named parameters and still be valid,
        // but we enforce that they are identical.
        for (int i = 0;
            i < uiConstructor.parameters.parameters.length &&
                i < webConstructor.parameters.parameters.length;
            i++) {
          final FormalParameter uiParam =
              uiConstructor.parameters.parameters[i];
          final FormalParameter webParam =
              webConstructor.parameters.parameters[i];
          if (webParam.name!.lexeme != uiParam.name!.lexeme) {
            failed = true;
            print('Warning: lib/ui/ui.dart $className.$name parameter $i'
                ' ${uiParam.name!.lexeme} has a different name in lib/web_ui/ui.dart.');
          }
          if (uiParam.isPositional != webParam.isPositional) {
            failed = true;
            print('Warning: lib/ui/ui.dart $className.$name parameter $i'
                '${uiParam.name!.lexeme} is positional, but not in lib/web_ui/ui.dart.');
          }
          if (uiParam.isNamed != webParam.isNamed) {
            failed = true;
            print('Warning: lib/ui/ui.dart $className.$name parameter $i'
                '${uiParam.name!.lexeme} is named, but not in lib/web_ui/ui.dart.');
          }
        }
      }
    }

    for (final String methodName in uiMethods.keys) {
      if (_kObjectMembers.contains(methodName)) {
        continue;
      }
      final MethodDeclaration uiMethod = uiMethods[methodName]!;
      final MethodDeclaration? webMethod = webMethods[methodName];
      if (webMethod == null) {
        failed = true;
        print(
          'Warning: lib/ui/ui.dart $className.$methodName is missing from lib/web_ui/ui.dart.',
        );
        continue;
      }
      if (uiMethod.parameters == null || webMethod.parameters == null) {
        continue;
      }
      if (uiMethod.parameters!.parameters.length !=
          webMethod.parameters!.parameters.length) {
        failed = true;
        print(
            'Warning: lib/ui/ui.dart $className.$methodName has a different parameter '
            'length than in lib/web_ui/ui.dart.');
      }
      // Technically you could re-order named parameters and still be valid,
      // but we enforce that they are identical.
      for (int i = 0;
          i < uiMethod.parameters!.parameters.length &&
              i < webMethod.parameters!.parameters.length;
          i++) {
        final FormalParameter uiParam = uiMethod.parameters!.parameters[i];
        final FormalParameter webParam = webMethod.parameters!.parameters[i];
        if (webParam.name!.lexeme != uiParam.name!.lexeme) {
          failed = true;
          print('Warning: lib/ui/ui.dart $className.$methodName parameter $i'
              ' ${uiParam.name!.lexeme} has a different name in lib/web_ui/ui.dart.');
        }
        if (uiParam.isPositional != webParam.isPositional) {
          failed = true;
          print('Warning: lib/ui/ui.dart $className.$methodName parameter $i'
              '${uiParam.name!.lexeme} is positional, but not in lib/web_ui/ui.dart.');
        }
        if (uiParam.isNamed != webParam.isNamed) {
          failed = true;
          print('Warning: lib/ui/ui.dart $className.$methodName parameter $i'
              '${uiParam.name!.lexeme} is named, but not in lib/web_ui/ui.dart.');
        }
        // check nullability
        if (uiParam is SimpleFormalParameter &&
            webParam is SimpleFormalParameter) {
          final bool isUiNullable = uiParam.type?.question != null;
          final bool isWebNullable = webParam.type?.question != null;
          if (isUiNullable != isWebNullable) {
            failed = true;
            print('Warning: lib/ui/ui.dart $className.$methodName parameter $i '
                '${uiParam.name} has a different nullability than in lib/web_ui/ui.dart.');
          }
        }
      }
      // check return type.
      if (uiMethod.returnType?.toString() != webMethod.returnType?.toString()) {
        // allow dynamic in web implementation.
        if (webMethod.returnType?.toString() != 'dynamic') {
          failed = true;
          print(
            'Warning: $className.$methodName return type mismatch:\n'
            '  lib/ui/ui.dart     : ${uiMethod.returnType?.toSource()}\n'
            '  lib/web_ui/ui.dart : ${webMethod.returnType?.toSource()}');
        }
      }
    }
  }
  print('Checking ${uiTypeDefs.length} typedefs.');
  for (final String typeDefName in uiTypeDefs.keys) {
    final GenericTypeAlias uiTypeDef = uiTypeDefs[typeDefName]!;
    final GenericTypeAlias? webTypeDef = webTypeDefs[typeDefName];
    // If the web typedef is missing there isn't much left to do here. Print a
    // warning and move along.
    if (webTypeDef == null) {
      failed = true;
      print('Warning: lib/ui/ui.dart contained typedef $typeDefName, but '
          'this was missing from lib/web_ui/ui.dart.');
      continue;
    }

    // uiTypeDef.functionType.parameters
    if (uiTypeDef.functionType?.parameters.parameters == null ||
        webTypeDef.functionType?.parameters.parameters == null) {
      continue;
    }
    if (uiTypeDef.functionType?.parameters.parameters.length !=
        webTypeDef.functionType?.parameters.parameters.length) {
      failed = true;
      print('Warning: lib/ui/ui.dart $typeDefName has a different parameter '
          'length than in lib/web_ui/ui.dart.');
    }
    // Technically you could re-order named parameters and still be valid,
    // but we enforce that they are identical.

    for (int i = 0;
        i < uiTypeDef.functionType!.parameters.parameters.length &&
            i < webTypeDef.functionType!.parameters.parameters.length;
        i++) {
      final SimpleFormalParameter uiParam =
          (uiTypeDef.type as GenericFunctionType).parameters.parameters[i]
              as SimpleFormalParameter;
      final SimpleFormalParameter webParam =
          (webTypeDef.type as GenericFunctionType).parameters.parameters[i]
              as SimpleFormalParameter;
      if (webParam.name == null) {
        failed = true;
        print('Warning: lib/web_ui/ui.dart $typeDefName parameter $i should have name.');
      }
      if (uiParam.name == null) {
        failed = true;
        print('Warning: lib/ui/ui.dart $typeDefName parameter $i should have name.');
      }
      if (webParam.name?.lexeme != uiParam.name?.lexeme) {
        failed = true;
        print('Warning: lib/ui/ui.dart $typeDefName parameter $i '
            '${uiParam.name!.lexeme} has a different name in lib/web_ui/ui.dart.');
      }
      if (uiParam.isPositional != webParam.isPositional) {
        failed = true;
        print('Warning: lib/ui/ui.dart $typeDefName parameter $i '
            '${uiParam.name!.lexeme} is positional, but not in lib/web_ui/ui.dart.');
      }
      if (uiParam.isNamed != webParam.isNamed) {
        failed = true;
        print('Warning: lib/ui/ui.dart $typeDefName parameter $i '
            '${uiParam.name!.lexeme}} is named, but not in lib/web_ui/ui.dart.');
      }

      final bool isUiNullable = uiParam.type?.question != null;
      final bool isWebNullable = webParam.type?.question != null;
      if (isUiNullable != isWebNullable) {
        failed = true;
        print('Warning: lib/ui/ui.dart $typeDefName parameter $i '
            '${uiParam.name} has a different nullability than in lib/web_ui/ui.dart.');
      }
    }

    // check return type.
    if (uiTypeDef.functionType?.returnType?.toString() !=
        webTypeDef.functionType?.returnType?.toString()) {
      // allow dynamic in web implementation.
      if (webTypeDef.functionType?.returnType?.toString() != 'dynamic') {
        failed = true;
        print('Warning: $typeDefName return type mismatch:\n'
            '  lib/ui/ui.dart     : ${uiTypeDef.functionType?.returnType?.toSource()}\n'
            '  lib/web_ui/ui.dart : ${webTypeDef.functionType?.returnType?.toSource()}');
      }
    }
  }
  if (failed) {
    print('Failure!');
    exit(1);
  }
  print('Success!');
  exit(0);
}

// Collects all public classes defined by the part files of [unit].
void _collectPublicClasses(CompilationUnit unit,
    Map<String, ClassDeclaration> destination, String root) {
  for (final Directive directive in unit.directives) {
    if (directive is! PartDirective) {
      continue;
    }
    final PartDirective partDirective = directive;
    final String literalUri = partDirective.uri.toString();
    final CompilationUnit subUnit = _parseAndCheckDart('$root${literalUri.substring(1, literalUri.length - 1)}');
    for (final CompilationUnitMember member in subUnit.declarations) {
      if (member is! ClassDeclaration) {
        continue;
      }
      final ClassDeclaration classDeclaration = member;
      if (classDeclaration.name.lexeme.startsWith('_')) {
        continue;
      }
      destination[classDeclaration.name.lexeme] = classDeclaration;
    }
  }
}

void _collectPublicConstructors(ClassDeclaration classDeclaration,
    Map<String, ConstructorDeclaration> destination) {
  for (final ClassMember member in classDeclaration.members) {
    if (member is! ConstructorDeclaration) {
      continue;
    }
    final String? methodName = member.name?.lexeme;
    if (methodName == null) {
      destination['Unnamed Constructor'] = member;
      continue;
    }
    if (methodName.startsWith('_')) {
      continue;
    }
    destination[methodName] = member;
  }
}

void _collectPublicMethods(ClassDeclaration classDeclaration,
    Map<String, MethodDeclaration> destination) {
  for (final ClassMember member in classDeclaration.members) {
    if (member is! MethodDeclaration) {
      continue;
    }
    if (member.name.lexeme.startsWith('_')) {
      continue;
    }
    destination[member.name.lexeme] = member;
  }
}

void _collectPublicTypeDefs(CompilationUnit unit,
    Map<String, GenericTypeAlias> destination, String root) {
  for (final Directive directive in unit.directives) {
    if (directive is! PartDirective) {
      continue;
    }
    final PartDirective partDirective = directive;
    final String literalUri = partDirective.uri.toString();
    final CompilationUnit subUnit = _parseAndCheckDart(
        '$root${literalUri.substring(1, literalUri.length - 1)}');
    for (final CompilationUnitMember member in subUnit.declarations) {
      if (member is! GenericTypeAlias) {
        continue;
      }
      final GenericTypeAlias typeDeclaration = member;
      if (typeDeclaration.name.lexeme.startsWith('_')) {
        continue;
      }
      destination[typeDeclaration.name.lexeme] = typeDeclaration;
    }
  }
}
