// Copyright (c) 2019, 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.

// @dart = 2.9

import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/services/flutter/class_description.dart';
import 'package:analysis_server/src/services/flutter/property.dart';
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/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:dart_style/dart_style.dart';

/// The result of [WidgetDescriptions.setPropertyValue] invocation.
class SetPropertyValueResult {
  /// The error to report to the client, or `null` if OK.
  final protocol.RequestErrorCode errorCode;

  /// The change to apply, or `null` if [errorCode] is not `null`.
  final protocol.SourceChange change;

  SetPropertyValueResult._({this.errorCode, this.change});
}

class WidgetDescriptions {
  final ClassDescriptionRegistry _classRegistry = ClassDescriptionRegistry();

  /// The mapping of identifiers of previously returned properties.
  final Map<int, PropertyDescription> _properties = {};

  /// Flush all data, because there was a change to a file.
  void flush() {
    _classRegistry.flush();
    _properties.clear();
  }

  /// Return the description of the widget with [InstanceCreationExpression] in
  /// the [resolvedUnit] at the [offset], or `null` if the location does not
  /// correspond to a widget.
  Future<protocol.FlutterGetWidgetDescriptionResult> getDescription(
    ResolvedUnitResult resolvedUnit,
    int offset,
  ) async {
    var computer = _WidgetDescriptionComputer(
      _classRegistry,
      resolvedUnit,
      offset,
    );
    var widgetDescription = await computer.compute();

    if (widgetDescription == null) {
      return null;
    }

    var protocolProperties = _toProtocolProperties(
      widgetDescription.properties,
    );
    return protocol.FlutterGetWidgetDescriptionResult(protocolProperties);
  }

  Future<SetPropertyValueResult> setPropertyValue(
    int id,
    protocol.FlutterWidgetPropertyValue value,
  ) async {
    var property = _properties[id];
    if (property == null) {
      return SetPropertyValueResult._(
        errorCode: protocol
            .RequestErrorCode.FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID,
      );
    }

    if (value == null) {
      if (property.protocolProperty.isRequired) {
        return SetPropertyValueResult._(
          errorCode: protocol
              .RequestErrorCode.FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED,
        );
      }
      var change = await property.removeValue();
      return SetPropertyValueResult._(change: change);
    } else {
      try {
        var change = await property.changeValue(value);
        return SetPropertyValueResult._(change: change);
      } on FormatterException {
        return SetPropertyValueResult._(
          errorCode: protocol.RequestErrorCode
              .FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION,
        );
      }
    }
  }

  List<protocol.FlutterWidgetProperty> _toProtocolProperties(
    List<PropertyDescription> properties,
  ) {
    var protocolProperties = <protocol.FlutterWidgetProperty>[];
    for (var property in properties) {
      var protocolProperty = property.protocolProperty;

      _properties[protocolProperty.id] = property;

      protocolProperty.children = _toProtocolProperties(property.children);
      protocolProperties.add(protocolProperty);
    }
    return protocolProperties;
  }
}

class _WidgetDescription {
  final List<PropertyDescription> properties;

  _WidgetDescription(this.properties);
}

class _WidgetDescriptionComputer {
  final ClassDescriptionRegistry classRegistry;

  /// The set of classes for which we are currently adding properties,
  /// used to prevent infinite recursion.
  final Set<ClassElement> classesBeingProcessed = <ClassElement>{};

  /// The resolved unit with the widget [InstanceCreationExpression].
  final ResolvedUnitResult resolvedUnit;

  /// The offset of the widget expression.
  final int widgetOffset;

  ClassElement _classAlignment;
  ClassElement _classAlignmentDirectional;
  ClassElement _classContainer;
  ClassElement _classEdgeInsets;

  _WidgetDescriptionComputer(
    this.classRegistry,
    this.resolvedUnit,
    this.widgetOffset,
  );

  Flutter get _flutter => Flutter.instance;

  Future<_WidgetDescription> compute() async {
    var node = NodeLocator2(widgetOffset).searchWithin(resolvedUnit.unit);
    var instanceCreation = _flutter.identifyNewExpression(node);
    if (instanceCreation == null) {
      return null;
    }

    var constructorElement = instanceCreation.constructorName.staticElement;
    if (constructorElement == null) {
      return null;
    }

    await _fetchClassElements();

    var properties = <PropertyDescription>[];
    _addProperties(
      properties: properties,
      instanceCreation: instanceCreation,
    );
    _addContainerProperty(properties, instanceCreation);

    return _WidgetDescription(properties);
  }

  void _addContainerProperty(
    List<PropertyDescription> properties,
    InstanceCreationExpression widgetCreation,
  ) {
    if (!_flutter.isWidgetCreation(widgetCreation)) {
      return;
    }

    InstanceCreationExpression parentCreation;
    var childArgument = widgetCreation.parent;
    if (childArgument is NamedExpression &&
        childArgument.name.label.name == 'child') {
      var argumentList = childArgument.parent;
      var argumentListParent = argumentList.parent;
      if (argumentList is ArgumentList &&
          argumentListParent is InstanceCreationExpression) {
        parentCreation = argumentListParent;
      }
    }

    PropertyDescription containerProperty;
    if (_flutter.isExactlyContainerCreation(parentCreation)) {
      containerProperty = PropertyDescription(
        resolvedUnit: resolvedUnit,
        instanceCreation: parentCreation,
        protocolProperty: protocol.FlutterWidgetProperty(
          PropertyDescription.nextId(),
          true,
          false,
          'Container',
        ),
      );
      properties.add(containerProperty);

      _addProperties(
        properties: containerProperty.children,
        parent: containerProperty,
        instanceCreation: parentCreation,
      );

      containerProperty.children.removeWhere(
        (property) => property.name == 'child',
      );
    } else {
      var containerDescription = classRegistry.get(_classContainer);
      containerProperty = PropertyDescription(
        resolvedUnit: resolvedUnit,
        classDescription: containerDescription,
        protocolProperty: protocol.FlutterWidgetProperty(
          PropertyDescription.nextId(),
          true,
          false,
          'Container',
        ),
        virtualContainer: VirtualContainerProperty(
          _classContainer,
          widgetCreation,
        ),
      );
      properties.add(containerProperty);

      _addProperties(
        properties: containerProperty.children,
        parent: containerProperty,
        classDescription: containerDescription,
      );

      if (_flutter.isExactlyAlignCreation(parentCreation) &&
          _flutter.findNamedArgument(parentCreation, 'widthFactor') == null &&
          _flutter.findNamedArgument(parentCreation, 'heightFactor') == null) {
        _replaceNestedContainerProperty(
          containerProperty,
          parentCreation,
          'alignment',
        );
      }

      if (_flutter.isExactlyPaddingCreation(parentCreation)) {
        _replaceNestedContainerProperty(
          containerProperty,
          parentCreation,
          'padding',
        );
      }
    }

    containerProperty.children.removeWhere(
      (property) => property.name == 'child',
    );
  }

  void _addProperties({
    List<PropertyDescription> properties,
    PropertyDescription parent,
    ClassDescription classDescription,
    InstanceCreationExpression instanceCreation,
    ConstructorElement constructorElement,
  }) {
    constructorElement ??= instanceCreation?.constructorName?.staticElement;
    constructorElement ??= classDescription?.constructor;
    if (constructorElement == null) return;

    var classElement = constructorElement.enclosingElement;
    if (!classesBeingProcessed.add(classElement)) return;

    var existingNamed = <String>{};
    if (instanceCreation != null) {
      for (var argumentExpression in instanceCreation.argumentList.arguments) {
        var parameter = argumentExpression.staticParameterElement;
        if (parameter == null) continue;

        Expression valueExpression;
        if (argumentExpression is NamedExpression) {
          valueExpression = argumentExpression.expression;
          existingNamed.add(parameter.name);
        } else {
          valueExpression = argumentExpression;
        }

        _addProperty(
          properties: properties,
          parent: parent,
          parameter: parameter,
          classDescription: classDescription,
          instanceCreation: instanceCreation,
          argumentExpression: argumentExpression,
          valueExpression: valueExpression,
        );
      }
    }

    for (var parameter in constructorElement.parameters) {
      if (!parameter.isNamed) continue;
      if (existingNamed.contains(parameter.name)) continue;

      _addProperty(
        properties: properties,
        parent: parent,
        parameter: parameter,
        classDescription: classDescription,
        instanceCreation: instanceCreation,
      );
    }

    classesBeingProcessed.remove(classElement);
  }

  void _addProperty({
    List<PropertyDescription> properties,
    PropertyDescription parent,
    ParameterElement parameter,
    ClassDescription classDescription,
    InstanceCreationExpression instanceCreation,
    Expression argumentExpression,
    Expression valueExpression,
  }) {
    var documentation = getParameterDocumentation(parameter);

    String valueExpressionCode;
    if (valueExpression != null) {
      valueExpressionCode = resolvedUnit.content.substring(
        valueExpression.offset,
        valueExpression.end,
      );
    }

    var isSafeToUpdate = false;
    protocol.FlutterWidgetPropertyValue value;
    if (valueExpression != null) {
      value = _toValue(valueExpression);
      isSafeToUpdate = value != null;
    } else {
      isSafeToUpdate = true;
    }

    var propertyDescription = PropertyDescription(
      parent: parent,
      resolvedUnit: resolvedUnit,
      flutter: _flutter,
      classDescription: classDescription,
      instanceCreation: instanceCreation,
      argumentExpression: argumentExpression,
      valueExpression: valueExpression,
      parameterElement: parameter,
      protocolProperty: protocol.FlutterWidgetProperty(
        PropertyDescription.nextId(),
        parameter.isRequiredPositional,
        isSafeToUpdate,
        parameter.name,
        documentation: documentation,
        editor: _getEditor(parameter.type),
        expression: valueExpressionCode,
        value: value,
      ),
    );
    properties.add(propertyDescription);

    if (_flutter.isExactEdgeInsetsGeometryType(parameter.type)) {
      propertyDescription.addEdgeInsetsNestedProperties(_classEdgeInsets);
    } else if (valueExpression is InstanceCreationExpression) {
      var type = valueExpression.staticType;
      if (classRegistry.hasNestedProperties(type)) {
        _addProperties(
          properties: propertyDescription.children,
          parent: propertyDescription,
          instanceCreation: valueExpression,
        );
      }
    } else if (valueExpression == null) {
      var type = parameter.type;
      if (type is InterfaceType) {
        var classDescription = classRegistry.get(
          type.element,
        );
        if (classDescription != null) {
          _addProperties(
            properties: propertyDescription.children,
            parent: propertyDescription,
            classDescription: classDescription,
          );
        }
      }
    }
  }

  List<protocol.FlutterWidgetPropertyValueEnumItem> _enumItemsForEnum(
    ClassElement element,
  ) {
    return element.fields
        .where((field) => field.isStatic && field.isEnumConstant)
        .map(_toEnumItem)
        .toList();
  }

  List<protocol.FlutterWidgetPropertyValueEnumItem> _enumItemsForStaticFields(
      ClassElement classElement) {
    return classElement.fields
        .where((f) => f.isStatic)
        .map(_toEnumItem)
        .toList();
  }

  Future<void> _fetchClassElements() async {
    var sessionHelper = AnalysisSessionHelper(resolvedUnit.session);
    _classAlignment = await sessionHelper.getClass(
      _flutter.widgetsUri,
      'Alignment',
    );
    _classAlignmentDirectional = await sessionHelper.getClass(
      _flutter.widgetsUri,
      'AlignmentDirectional',
    );
    _classContainer = await sessionHelper.getClass(
      _flutter.widgetsUri,
      'Container',
    );
    _classEdgeInsets = await sessionHelper.getClass(
      _flutter.widgetsUri,
      'EdgeInsets',
    );
  }

  protocol.FlutterWidgetPropertyEditor _getEditor(DartType type) {
    if (type.isDartCoreBool) {
      return protocol.FlutterWidgetPropertyEditor(
        protocol.FlutterWidgetPropertyEditorKind.BOOL,
      );
    }
    if (type.isDartCoreDouble) {
      return protocol.FlutterWidgetPropertyEditor(
        protocol.FlutterWidgetPropertyEditorKind.DOUBLE,
      );
    }
    if (type.isDartCoreInt) {
      return protocol.FlutterWidgetPropertyEditor(
        protocol.FlutterWidgetPropertyEditorKind.INT,
      );
    }
    if (type.isDartCoreString) {
      return protocol.FlutterWidgetPropertyEditor(
        protocol.FlutterWidgetPropertyEditorKind.STRING,
      );
    }
    if (type is InterfaceType) {
      var classElement = type.element;
      if (classElement.isEnum) {
        return protocol.FlutterWidgetPropertyEditor(
          protocol.FlutterWidgetPropertyEditorKind.ENUM,
          enumItems: _enumItemsForEnum(classElement),
        );
      }
      if (_flutter.isExactAlignmentGeometry(classElement)) {
        var items = <protocol.FlutterWidgetPropertyValueEnumItem>[];
        items.addAll(
          _enumItemsForStaticFields(_classAlignment),
        );
        items.addAll(
          _enumItemsForStaticFields(_classAlignmentDirectional),
        );
        return protocol.FlutterWidgetPropertyEditor(
          protocol.FlutterWidgetPropertyEditorKind.ENUM_LIKE,
          enumItems: items,
        );
      }
    }
    return null;
  }

  /// If the [parentCreation] has a property with the given [name], replace
  /// with it the corresponding nested property of the [containerProperty].
  void _replaceNestedContainerProperty(
    PropertyDescription containerProperty,
    InstanceCreationExpression parentCreation,
    String name,
  ) {
    var argument = _flutter.findNamedArgument(parentCreation, name);
    if (argument != null) {
      var replacements = <PropertyDescription>[];
      _addProperty(
        properties: replacements,
        parent: containerProperty,
        parameter: argument.staticParameterElement,
        instanceCreation: parentCreation,
        argumentExpression: argument,
        valueExpression: argument.expression,
      );

      var replacement = replacements[0];
      if (replacement != null) {
        containerProperty.replaceChild(name, replacement);
        containerProperty.virtualContainer.setParentCreation(
          parentCreation,
          argument,
        );
      }
    }
  }

  protocol.FlutterWidgetPropertyValueEnumItem _toEnumItem(FieldElement field) {
    var classElement = field.enclosingElement as ClassElement;
    var libraryUriStr = '${classElement.library.source.uri}';
    var documentation = getFieldDocumentation(field);

    return protocol.FlutterWidgetPropertyValueEnumItem(
      libraryUriStr,
      classElement.name,
      field.name,
      documentation: documentation,
    );
  }

  protocol.FlutterWidgetPropertyValue _toValue(Expression valueExpression) {
    if (valueExpression is BooleanLiteral) {
      return protocol.FlutterWidgetPropertyValue(
        boolValue: valueExpression.value,
      );
    } else if (valueExpression is DoubleLiteral) {
      return protocol.FlutterWidgetPropertyValue(
        doubleValue: valueExpression.value,
      );
    } else if (valueExpression is Identifier) {
      var element = valueExpression.staticElement;
      if (element is PropertyAccessorElement && element.isGetter) {
        var field = element.variable;
        if (field is FieldElement && field.isStatic) {
          var enclosingClass = field.enclosingElement as ClassElement;
          if (field.isEnumConstant ||
              _flutter.isExactAlignment(enclosingClass) ||
              _flutter.isExactAlignmentDirectional(enclosingClass)) {
            return protocol.FlutterWidgetPropertyValue(
              enumValue: _toEnumItem(field),
            );
          }
        }
      }
    } else if (valueExpression is IntegerLiteral) {
      return protocol.FlutterWidgetPropertyValue(
        intValue: valueExpression.value,
      );
    } else if (valueExpression is SimpleStringLiteral) {
      return protocol.FlutterWidgetPropertyValue(
        stringValue: valueExpression.value,
      );
    }
    return null;
  }
}
