// Copyright (c) 2021, 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:analysis_server/src/utilities/flutter.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/constant/value.dart' show GenericState;
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:collection/collection.dart';

/// Computer for dart:ui/Flutter Color references.
class ColorComputer {
  final ResolvedUnitResult resolvedUnit;
  final LinterContext _linterContext;
  final List<ColorReference> _colors = [];
  final Flutter _flutter = Flutter.instance;

  ColorComputer(this.resolvedUnit)
      : _linterContext = LinterContextImpl(
          [], // unused
          LinterContextUnit(resolvedUnit.content, resolvedUnit.unit),
          resolvedUnit.session.declaredVariables,
          resolvedUnit.typeProvider,
          resolvedUnit.typeSystem as TypeSystemImpl,
          InheritanceManager3(), // unused
          resolvedUnit.session.analysisContext.analysisOptions,
          null,
        );

  /// Returns information about the color references in [resolvedUnit].
  ///
  /// This method should only be called once for any instance of this class.
  List<ColorReference> compute() {
    final visitor = _ColorBuilder(this);
    resolvedUnit.unit.accept(visitor);
    return _colors;
  }

  /// Tries to add a color for the [expression].
  ///
  /// If [target] is supplied, will be used instead of [expression] allowing
  /// a value to be read from the member [memberName] or from a swatch value
  /// with index [index].
  bool tryAddColor(
    Expression expression, {
    Expression? target,
    String? memberName,
    int? index,
  }) {
    if (!_isColor(expression.staticType)) return false;

    target ??= expression;

    // Try to evaluate the constant target.
    final colorConstResult = _linterContext.evaluateConstant(target);
    var colorConst = colorConstResult.value;
    if (colorConstResult.errors.isNotEmpty || colorConst == null) return false;

    // If we want a specific member or swatch index, read that.
    if (memberName != null) {
      colorConst = _getMember(colorConst, memberName);
    } else if (index != null) {
      colorConst = _getSwatchValue(colorConst, index);
    }

    return _tryRecordColor(expression, colorConst);
  }

  /// Tries to add a color for the instance creation [expression].
  ///
  /// This handles constructor calls that cannot be evaluated (for example
  /// because they are not const) but are simple well-known dart:ui/Flutter
  /// color constructors that we can manually parse.
  bool tryAddKnownColorConstructor(InstanceCreationExpression expression) {
    if (!_isColor(expression.staticType)) return false;

    final constructor = expression.constructorName;
    final staticElement = constructor.staticElement;
    final classElement = staticElement?.enclosingElement;
    final className = classElement?.name;
    final constructorName = constructor.name?.name;
    final constructorArgs = expression.argumentList.arguments
        .map((e) => e is Literal ? e : null)
        .toList();

    int? colorValue;
    if (_isDartUi(classElement) && className == 'Color') {
      colorValue = _getDartUiColorValue(constructorName, constructorArgs);
    } else if (_isFlutterPainting(classElement) && className == 'ColorSwatch') {
      colorValue =
          _getFlutterSwatchColorValue(constructorName, constructorArgs);
    } else if (_isFlutterMaterial(classElement) &&
        className == 'MaterialAccentColor') {
      colorValue =
          _getFlutterMaterialAccentColorValue(constructorName, constructorArgs);
    }

    return _tryRecordColorValue(expression, colorValue);
  }

  /// Creates a [ColorInformation] by extracting the argb values from
  /// [value] encoded as 0xAARRGGBB as in the dart:ui Color class.
  ColorInformation _colorInformationForColorValue(int value) {
    // Extract color information according to dart:ui Color values.
    final alpha = (0xff000000 & value) >> 24;
    final red = (0x00ff0000 & value) >> 16;
    final blue = (0x000000ff & value) >> 0;
    final green = (0x0000ff00 & value) >> 8;

    return ColorInformation(alpha, red, green, blue);
  }

  /// Extracts the integer color value from the dart:ui Color constant [color].
  int? _colorValueForColorConst(DartObject? color) {
    if (color == null || color.isNull) return null;

    // If the object has a "color" field, walk down to that, because some colors
    // like CupertinoColors have a "value=0" with an overridden getter that
    // would always result in a value representing black.
    color = color.getFieldFromHierarchy('color') ?? color;

    return color.getFieldFromHierarchy('value')?.toIntValue();
  }

  /// Converts ARGB values into a single int value as 0xAARRGGBB as used by
  /// the dart:ui Color class.
  int _colorValueForComponents(int alpha, int red, int green, int blue) {
    return (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
  }

  /// Extracts the color value from dart:ui Color constructor args.
  int? _getDartUiColorValue(String? name, List<Literal?> args) {
    if (name == null && args.length == 1) {
      final arg0 = args[0];
      return arg0 is IntegerLiteral ? arg0.value : null;
    } else if (name == 'fromARGB' && args.length == 4) {
      final arg0 = args[0];
      final arg1 = args[1];
      final arg2 = args[2];
      final arg3 = args[3];

      final alpha = arg0 is IntegerLiteral ? arg0.value : null;
      final red = arg1 is IntegerLiteral ? arg1.value : null;
      final green = arg2 is IntegerLiteral ? arg2.value : null;
      final blue = arg3 is IntegerLiteral ? arg3.value : null;

      return alpha != null && red != null && green != null && blue != null
          ? _colorValueForComponents(alpha, red, green, blue)
          : null;
    } else if (name == 'fromRGBO' && args.length == 4) {
      final arg0 = args[0];
      final arg1 = args[1];
      final arg2 = args[2];
      final arg3 = args[3];

      final red = arg0 is IntegerLiteral ? arg0.value : null;
      final green = arg1 is IntegerLiteral ? arg1.value : null;
      final blue = arg2 is IntegerLiteral ? arg2.value : null;
      final opacity = arg3 is IntegerLiteral
          ? arg3.value
          : arg3 is DoubleLiteral
              ? arg3.value
              : null;
      final alpha = opacity != null ? (opacity * 255).toInt() : null;

      return alpha != null && red != null && green != null && blue != null
          ? _colorValueForComponents(alpha, red, green, blue)
          : null;
    }
  }

  /// Extracts the color value from Flutter MaterialAccentColor constructor args.
  int? _getFlutterMaterialAccentColorValue(String? name, List<Literal?> args) =>
      // MaterialAccentColor is a subclass of SwatchColor and has the same
      // constructor.
      _getFlutterSwatchColorValue(name, args);

  /// Extracts the color value from Flutter ColorSwatch constructor args.
  int? _getFlutterSwatchColorValue(String? name, List<Literal?> args) {
    if (name == null && args.isNotEmpty) {
      final arg0 = args[0];
      return arg0 is IntegerLiteral ? arg0.value : null;
    }
  }

  /// Extracts a named member from a color.
  ///
  /// Well-known getters like `shade500` will be mapped onto the swatch value
  /// with a matching index.
  DartObject? _getMember(DartObject target, String memberName) {
    final colorValue = target.getFieldFromHierarchy(memberName);
    if (colorValue != null) {
      return colorValue;
    }

    // If we didn't get a value but it's a getter we know how to read from a
    // swatch, try that.
    if (memberName.startsWith('shade')) {
      final shadeNumber = int.tryParse(memberName.substring(5));
      if (shadeNumber != null) {
        return _getSwatchValue(target, shadeNumber);
      }
    }
  }

  /// Extracts a specific shade index from a Flutter SwatchColor.
  DartObject? _getSwatchValue(DartObject target, int swatchValue) {
    final swatch = target.getFieldFromHierarchy('_swatch')?.toMapValue();
    if (swatch == null) return null;

    final key = swatch.keys.firstWhereOrNull(
      (key) => key?.toIntValue() == swatchValue,
    );
    if (key == null) return null;

    return swatch[key];
  }

  /// Checks whether [type] is - or extends - the dart:ui Color class.
  bool _isColor(DartType? type) => type != null && _flutter.isColor(type);

  /// Checks whether this elements library is dart:ui.
  bool _isDartUi(Element? element) => element?.library?.name == 'dart.ui';

  /// Checks whether this elements library is Flutter Material colors.
  bool _isFlutterMaterial(Element? element) =>
      element?.library?.identifier ==
      'package:flutter/src/material/colors.dart';

  /// Checks whether this elements library is Flutter Painting colors.
  bool _isFlutterPainting(Element? element) =>
      element?.library?.identifier ==
      'package:flutter/src/painting/colors.dart';

  /// Tries to record a color value from [colorConst] for [expression].
  ///
  /// Returns whether a valid color was found and recorded.
  bool _tryRecordColor(Expression expression, DartObject? colorConst) =>
      _tryRecordColorValue(expression, _colorValueForColorConst(colorConst));

  /// Tries to record the [colorValue] for [expression].
  ///
  /// Returns whether a valid color was found and recorded.
  bool _tryRecordColorValue(Expression expression, int? colorValue) {
    if (colorValue == null) return false;

    // Build color information from the Color value.
    final color = _colorInformationForColorValue(colorValue);

    // Record the color against the original entire expression.
    _colors.add(ColorReference(expression.offset, expression.length, color));
    return true;
  }
}

/// Information about a color that is present in a document.
class ColorInformation {
  final int alpha;
  final int red;
  final int green;
  final int blue;

  ColorInformation(this.alpha, this.red, this.green, this.blue);
}

/// Information about a specific known location of a [ColorInformation]
/// reference in a document.
class ColorReference {
  final int offset;
  final int length;
  final ColorInformation color;

  ColorReference(this.offset, this.length, this.color);
}

class _ColorBuilder extends RecursiveAstVisitor<void> {
  final ColorComputer computer;

  _ColorBuilder(this.computer);

  @override
  void visitIndexExpression(IndexExpression node) {
    // Colors.redAccent[500].
    final index = node.index;
    final indexValue = index is IntegerLiteral ? index.value : null;
    if (indexValue != null) {
      if (computer.tryAddColor(
        node,
        target: node.realTarget,
        index: indexValue,
      )) {
        return;
      }
    }
    super.visitIndexExpression(node);
  }

  @override
  void visitInstanceCreationExpression(InstanceCreationExpression node) {
    // Usually we return after finding a color, but constructors can
    // have nested colors in their arguments so we walk all the way down.
    if (!computer.tryAddColor(node)) {
      // If we couldn't evaluate the constant, try the well-known color
      // constructors for dart:ui/Flutter.
      computer.tryAddKnownColorConstructor(node);
    }

    super.visitInstanceCreationExpression(node);
  }

  @override
  void visitPrefixedIdentifier(PrefixedIdentifier node) {
    // Try the whole node as a constant (eg. `MyThemeClass.staticField`).
    if (computer.tryAddColor(node)) {
      return;
    }

    // Try a field of a static, (eg. `const MyThemeClass().instanceField`).
    if (computer.tryAddColor(
      node,
      target: node.prefix,
      memberName: node.identifier.name,
    )) {
      return;
    }

    super.visitPrefixedIdentifier(node);
  }

  @override
  void visitPropertyAccess(PropertyAccess node) {
    // Handle things like CupterinoColors.activeBlue.darkColor where we can't
    // evaluate the whole expression, but can evaluate CupterinoColors.activeBlue
    // and read the darkColor.
    if (computer.tryAddColor(
      node,
      target: node.realTarget,
      memberName: node.propertyName.name,
    )) {
      return;
    }

    super.visitPropertyAccess(node);
  }
}

extension _DartObjectExtensions on DartObject {
  /// Reads the value of the field [field] from this object.
  ///
  /// If the field is not found, recurses up the super classes.
  DartObject? getFieldFromHierarchy(String fieldName) =>
      getField(fieldName) ??
      getField(GenericState.SUPERCLASS_FIELD)?.getFieldFromHierarchy(fieldName);
}
