// Copyright (c) 2020, 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:kernel/class_hierarchy.dart';
import 'package:kernel/kernel.dart';

/// Provides support for "single widget reloads" in Flutter, by determining if
/// a partial component contains single change to the class body of a
/// StatelessWidget, StatefulWidget, or State subtype.
class WidgetCache {
  /// Create a [WidgetCache] from a [Component] containing the flutter
  /// framework.
  WidgetCache(Component fullComponent) {
    Library? frameworkLibrary;
    for (Library library in fullComponent.libraries) {
      if (library.importUri == _frameworkLibrary) {
        frameworkLibrary = library;
        break;
      }
    }
    if (frameworkLibrary == null) {
      return;
    }
    _locatedClassDeclarations(frameworkLibrary);
    _frameworkTypesLocated =
        _statefulWidget != null && _state != null && _statelessWidget != null;
  }

  static const String _stateClassName = 'State';
  static const String _statefulWidgetClassName = 'StatefulWidget';
  static const String _statelessWidgetClassName = 'StatelessWidget';

  Class? _statelessWidget;
  Class? _state;
  Class? _statefulWidget;
  bool _frameworkTypesLocated = false;

  static final Uri _frameworkLibrary =
      Uri.parse('package:flutter/src/widgets/framework.dart');

  /// Mark [uri] as invalidated.
  void invalidate(Uri uri) {
    _invalidatedLibraries.add(uri);
  }

  /// Reset the invalidated libraries.
  void reset() {
    _invalidatedLibraries.clear();
  }

  final List<Uri> _invalidatedLibraries = <Uri>[];

  /// Determine if any changes to [partialComponent] were located entirely
  /// within the class body of a single `StatefulWidget`, `StatelessWidget` or
  /// `State` subtype.
  ///
  /// Returns the class name if located, otherwise `null`.
  String? checkSingleWidgetTypeModified(
    Component? lastGoodComponent,
    Component partialComponent,
    ClassHierarchy? classHierarchy,
  ) {
    if (!_frameworkTypesLocated ||
        lastGoodComponent == null ||
        _invalidatedLibraries.length != 1) {
      return null;
    }
    Uri importUri = _invalidatedLibraries[0];
    Library? library;
    for (Library candidateLibrary in partialComponent.libraries) {
      if (candidateLibrary.importUri == importUri) {
        library = candidateLibrary;
        break;
      }
    }
    if (library == null) {
      return null;
    }
    List<int> oldSource =
        lastGoodComponent.uriToSource[library.fileUri]!.source;
    List<int> newSource = partialComponent.uriToSource[library.fileUri]!.source;
    // Library was added and does not exist in the old component.
    // ignore: unnecessary_null_comparison
    if (oldSource == null) {
      return null;
    }
    int newStartIndex = 0;
    int newEndIndex = newSource.length - 1;
    int oldStartIndex = 0;
    int oldEndIndex = oldSource.length - 1;

    while (newStartIndex < newEndIndex && oldStartIndex < oldEndIndex) {
      if (newSource[newStartIndex] != oldSource[oldStartIndex]) {
        break;
      }
      newStartIndex += 1;
      oldStartIndex += 1;
    }
    while (newEndIndex > newStartIndex && oldEndIndex > oldStartIndex) {
      if (newSource[newEndIndex] != oldSource[oldEndIndex]) {
        break;
      }
      newEndIndex -= 1;
      oldEndIndex -= 1;
    }

    Class? newClass =
        _locateContainingClass(library, newStartIndex, newEndIndex);
    if (newClass == null) {
      return null;
    }

    Library oldLibrary =
        lastGoodComponent.libraries.firstWhere((Library library) {
      return library.importUri == importUri;
    });

    Class? oldClass =
        _locateContainingClass(oldLibrary, oldStartIndex, oldEndIndex);

    if (oldClass == null || oldClass.name != newClass.name) {
      return null;
    }

    // Update the class references to stateless, stateful, and state classes.
    for (Library library in classHierarchy!.knownLibraries) {
      if (library.importUri == _frameworkLibrary) {
        _locatedClassDeclarations(library);
      }
    }

    if (classHierarchy.isSubclassOf(newClass, _statelessWidget!) ||
        classHierarchy.isSubclassOf(newClass, _statefulWidget!)) {
      if (classHierarchy.isExtended(newClass) ||
          classHierarchy.isUsedAsMixin(newClass)) {
        return null;
      }
      return newClass.name;
    }

    // For changes to State classes, locate the name of the corresponding
    // StatefulWidget that is provided as a type parameter. If the bounds are
    // StatefulWidget itself, fail as that indicates the type was not
    // specified.
    Supertype? stateSuperType =
        classHierarchy.getClassAsInstanceOf(newClass, _state!);
    if (stateSuperType != null) {
      if (stateSuperType.typeArguments.length != 1) {
        return null;
      }
      DartType widgetType = stateSuperType.typeArguments[0];
      if (widgetType is InterfaceType) {
        Class statefulWidgetType = widgetType.classNode;
        if (statefulWidgetType.name == _statefulWidgetClassName) {
          return null;
        }
        if (classHierarchy.isExtended(statefulWidgetType) ||
            classHierarchy.isUsedAsMixin(statefulWidgetType)) {
          return null;
        }
        return statefulWidgetType.name;
      }
    }

    return null;
  }

  // Locate the that fully contains the edit range, or null.
  Class? _locateContainingClass(
      Library library, int startOffset, int endOffset) {
    for (Class classDeclaration in library.classes) {
      if (classDeclaration.startFileOffset <= startOffset &&
          classDeclaration.fileEndOffset >= endOffset) {
        return classDeclaration;
      }
    }
    return null;
  }

  void _locatedClassDeclarations(Library library) {
    for (Class classDeclaration in library.classes) {
      if (classDeclaration.name == _statelessWidgetClassName) {
        _statelessWidget = classDeclaration;
      } else if (classDeclaration.name == _statefulWidgetClassName) {
        _statefulWidget = classDeclaration;
      } else if (classDeclaration.name == _stateClassName) {
        _state = classDeclaration;
      }
    }
  }
}
