// Copyright (c) 2018, 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/computer/computer_outline.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/protocol_server.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/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/source.dart';

/// Computer for Flutter specific outlines.
class FlutterOutlineComputer {
  static const CONSTRUCTOR_NAME = 'forDesignTime';

  /// Code to append to the instrumented library code.
  static const RENDER_APPEND = r'''

final flutterDesignerWidgets = <int, Widget>{};

T _registerWidgetInstance<T extends Widget>(int id, T widget) {
  flutterDesignerWidgets[id] = widget;
  return widget;
}
''';

  final ResolvedUnitResult resolvedUnit;
  Flutter flutter;

  final List<protocol.FlutterOutline> _depthFirstOrder = [];

  int nextWidgetId = 0;

  /// This map is filled with information about widget classes that can be
  /// rendered. Its keys are class name offsets.
  final Map<int, _WidgetClass> widgets = {};

  final List<protocol.SourceEdit> instrumentationEdits = [];
  String instrumentedCode;

  FlutterOutlineComputer(this.resolvedUnit);

  protocol.FlutterOutline compute() {
    protocol.Outline dartOutline = new DartUnitOutlineComputer(
      resolvedUnit,
      withBasicFlutter: false,
    ).compute();

    flutter = Flutter.of(resolvedUnit);

    // Find widget classes.
    // IDEA plugin only supports rendering widgets in libraries.
    var unitElement = resolvedUnit.unit.declaredElement;
    if (unitElement.source == unitElement.librarySource) {
      _findWidgets();
    }

    // Convert Dart outlines into Flutter outlines.
    var flutterDartOutline = _convert(dartOutline);

    // Create outlines for widgets.
    resolvedUnit.unit.accept(new _FlutterOutlineBuilder(this));

    // Compute instrumented code.
    if (widgets.values.any((w) => w.hasDesignTimeConstructor)) {
      _rewriteRelativeDirectives();
      instrumentationEdits.sort((a, b) => b.offset - a.offset);
      instrumentedCode = SourceEdit.applySequence(
        resolvedUnit.content,
        instrumentationEdits,
      );
      instrumentedCode += RENDER_APPEND;
    }

    return flutterDartOutline;
  }

  /// If the given [argument] for the [parameter] can be represented as a
  /// Flutter attribute, add it to the [attributes].
  void _addAttribute(List<protocol.FlutterOutlineAttribute> attributes,
      Expression argument, ParameterElement parameter) {
    if (parameter == null) {
      return;
    }
    if (argument is NamedExpression) {
      argument = (argument as NamedExpression).expression;
    }

    String name = parameter.displayName;

    var label = resolvedUnit.content.substring(argument.offset, argument.end);
    if (label.contains('\n')) {
      label = '…';
    }

    if (argument is BooleanLiteral) {
      attributes.add(new protocol.FlutterOutlineAttribute(name, label,
          literalValueBoolean: argument.value));
    } else if (argument is IntegerLiteral) {
      attributes.add(new protocol.FlutterOutlineAttribute(name, label,
          literalValueInteger: argument.value));
    } else if (argument is StringLiteral) {
      attributes.add(new protocol.FlutterOutlineAttribute(name, label,
          literalValueString: argument.stringValue));
    } else {
      if (argument is FunctionExpression) {
        bool hasParameters = argument.parameters != null &&
            argument.parameters.parameters.isNotEmpty;
        if (argument.body is ExpressionFunctionBody) {
          label = hasParameters ? '(…) => …' : '() => …';
        } else {
          label = hasParameters ? '(…) { … }' : '() { … }';
        }
      } else if (argument is ListLiteral) {
        label = '[…]';
      } else if (argument is SetOrMapLiteral) {
        label = '{…}';
      }
      attributes.add(new protocol.FlutterOutlineAttribute(name, label));
    }
  }

  int _addInstrumentationEdits(Expression expression) {
    int id = nextWidgetId++;
    instrumentationEdits.add(new protocol.SourceEdit(
        expression.offset, 0, '_registerWidgetInstance($id, '));
    instrumentationEdits.add(new protocol.SourceEdit(expression.end, 0, ')'));
    return id;
  }

  protocol.FlutterOutline _convert(protocol.Outline dartOutline) {
    protocol.FlutterOutline flutterOutline = new protocol.FlutterOutline(
        protocol.FlutterOutlineKind.DART_ELEMENT,
        dartOutline.offset,
        dartOutline.length,
        dartOutline.codeOffset,
        dartOutline.codeLength,
        dartElement: dartOutline.element);
    if (dartOutline.children != null) {
      flutterOutline.children = dartOutline.children.map(_convert).toList();
    }

    // Fill rendering information for widget classes.
    if (dartOutline.element.kind == protocol.ElementKind.CLASS) {
      var widget = widgets[dartOutline.element.location.offset];
      if (widget != null) {
        flutterOutline.isWidgetClass = true;
        if (widget.hasDesignTimeConstructor) {
          flutterOutline.renderConstructor = CONSTRUCTOR_NAME;
        }
        flutterOutline.stateClassName = widget.state?.name?.name;
        flutterOutline.stateOffset = widget.state?.offset;
        flutterOutline.stateLength = widget.state?.length;
      }
    }

    _depthFirstOrder.add(flutterOutline);
    return flutterOutline;
  }

  /// If the [node] is a supported Flutter widget creation, create a new
  /// outline item for it. If the node is not a widget creation, but its type
  /// is a Flutter Widget class subtype, and [withGeneric] is `true`, return
  /// a widget reference outline item.
  protocol.FlutterOutline _createOutline(Expression node, bool withGeneric) {
    DartType type = node.staticType;
    if (!flutter.isWidgetType(type)) {
      return null;
    }
    String className = type.element.displayName;

    if (node is InstanceCreationExpression) {
      int id = _addInstrumentationEdits(node);

      var attributes = <protocol.FlutterOutlineAttribute>[];
      var children = <protocol.FlutterOutline>[];
      for (var argument in node.argumentList.arguments) {
        bool isWidgetArgument = flutter.isWidgetType(argument.staticType);
        bool isWidgetListArgument =
            flutter.isListOfWidgetsType(argument.staticType);

        String parentAssociationLabel;
        Expression childrenExpression;

        if (argument is NamedExpression) {
          parentAssociationLabel = argument.name.label.name;
          childrenExpression = argument.expression;
        } else {
          childrenExpression = argument;
        }

        if (isWidgetArgument) {
          var child = _createOutline(childrenExpression, true);
          if (child != null) {
            child.parentAssociationLabel = parentAssociationLabel;
            children.add(child);
          }
        } else if (isWidgetListArgument) {
          if (childrenExpression is ListLiteral) {
            for (var element in childrenExpression.elements) {
              void addChildrenFrom(CollectionElement element) {
                if (element is Expression) {
                  var child = _createOutline(element, true);
                  if (child != null) {
                    children.add(child);
                  }
                } else if (element is IfElement) {
                  addChildrenFrom(element.thenElement);
                  addChildrenFrom(element.elseElement);
                } else if (element is ForElement) {
                  addChildrenFrom(element.body);
                } else if (element is SpreadElement) {
                  // Ignored. It's possible that we might be able to extract
                  // some information from some spread expressions, but it seems
                  // unlikely enough that we're not handling it at the moment.
                }
              }

              addChildrenFrom(element);
            }
          }
        } else {
          ParameterElement parameter = argument.staticParameterElement;
          _addAttribute(attributes, argument, parameter);
        }
      }

      return new protocol.FlutterOutline(
          protocol.FlutterOutlineKind.NEW_INSTANCE,
          node.offset,
          node.length,
          node.offset,
          node.length,
          className: className,
          attributes: attributes,
          children: children,
          id: id);
    }

    // A generic Widget typed expression.
    if (withGeneric) {
      var kind = protocol.FlutterOutlineKind.GENERIC;

      String variableName;
      if (node is SimpleIdentifier) {
        kind = protocol.FlutterOutlineKind.VARIABLE;
        variableName = node.name;
      }

      String label;
      if (kind == protocol.FlutterOutlineKind.GENERIC) {
        label = _getShortLabel(node);
      }

      int id = _addInstrumentationEdits(node);
      return new protocol.FlutterOutline(
          kind, node.offset, node.length, node.offset, node.length,
          className: className,
          variableName: variableName,
          label: label,
          id: id);
    }

    return null;
  }

  /// Return the `State` declaration for the given `StatefulWidget` declaration.
  /// Return `null` if cannot be found.
  ClassDeclaration _findState(ClassDeclaration widget) {
    MethodDeclaration createStateMethod = widget.members.firstWhere(
        (method) =>
            method is MethodDeclaration &&
            method.name.name == 'createState' &&
            method.body != null,
        orElse: () => null);
    if (createStateMethod == null) {
      return null;
    }

    DartType stateType;
    {
      FunctionBody buildBody = createStateMethod.body;
      if (buildBody is ExpressionFunctionBody) {
        stateType = buildBody.expression.staticType;
      } else if (buildBody is BlockFunctionBody) {
        List<Statement> statements = buildBody.block.statements;
        if (statements.isNotEmpty) {
          Statement lastStatement = statements.last;
          if (lastStatement is ReturnStatement) {
            stateType = lastStatement.expression?.staticType;
          }
        }
      }
    }
    if (stateType == null) {
      return null;
    }

    ClassElement stateElement;
    if (stateType is InterfaceType && flutter.isState(stateType.element)) {
      stateElement = stateType.element;
    } else {
      return null;
    }

    for (var stateNode in resolvedUnit.unit.declarations) {
      if (stateNode is ClassDeclaration &&
          stateNode.declaredElement == stateElement) {
        return stateNode;
      }
    }

    return null;
  }

  /// Fill [widgets] with information about classes that can be rendered.
  void _findWidgets() {
    for (var widget in resolvedUnit.unit.declarations) {
      if (widget is ClassDeclaration) {
        int nameOffset = widget.name.offset;

        var designTimeConstructor = widget.getConstructor(CONSTRUCTOR_NAME);
        bool hasDesignTimeConstructor = designTimeConstructor != null;

        InterfaceType superType = widget.declaredElement.supertype;
        if (flutter.isExactlyStatelessWidgetType(superType)) {
          widgets[nameOffset] =
              new _WidgetClass(nameOffset, hasDesignTimeConstructor);
        } else if (flutter.isExactlyStatefulWidgetType(superType)) {
          ClassDeclaration state = _findState(widget);
          if (state != null) {
            widgets[nameOffset] =
                new _WidgetClass(nameOffset, hasDesignTimeConstructor, state);
          }
        }
      }
    }
  }

  String _getShortLabel(AstNode node) {
    if (node is MethodInvocation) {
      var buffer = new StringBuffer();

      if (node.target != null) {
        buffer.write(_getShortLabel(node.target));
        buffer.write('.');
      }

      buffer.write(node.methodName.name);

      if (node.argumentList == null || node.argumentList.arguments.isEmpty) {
        buffer.write('()');
      } else {
        buffer.write('(…)');
      }

      return buffer.toString();
    }
    return node.toString();
  }

  /// The instrumented code is put into a temporary directory for Dart VM to
  /// run. So, any relative URIs must be changed to corresponding absolute URIs.
  void _rewriteRelativeDirectives() {
    for (var directive in resolvedUnit.unit.directives) {
      if (directive is UriBasedDirective) {
        String uriContent = directive.uriContent;
        Source source = directive.uriSource;
        if (uriContent != null && source != null) {
          try {
            if (!Uri.parse(uriContent).isAbsolute) {
              instrumentationEdits.add(new SourceEdit(directive.uri.offset,
                  directive.uri.length, "'${source.uri}'"));
            }
          } on FormatException {}
        }
      }
    }
  }
}

class _FlutterOutlineBuilder extends GeneralizingAstVisitor<void> {
  final FlutterOutlineComputer computer;

  _FlutterOutlineBuilder(this.computer);

  @override
  void visitExpression(Expression node) {
    var outline = computer._createOutline(node, false);
    if (outline != null) {
      for (var parent in computer._depthFirstOrder) {
        if (parent.offset < outline.offset &&
            outline.offset + outline.length < parent.offset + parent.length) {
          parent.children ??= <protocol.FlutterOutline>[];
          parent.children.add(outline);
          return;
        }
      }
    } else {
      super.visitExpression(node);
    }
  }
}

/// Information about a Widget class that can be rendered.
class _WidgetClass {
  final int nameOffset;

  /// Is `true` if has `forDesignTime` constructor, so can be rendered.
  final bool hasDesignTimeConstructor;

  /// If a `StatefulWidget` with the `State` in the same file.
  final ClassDeclaration state;

  _WidgetClass(this.nameOffset, this.hasDesignTimeConstructor, [this.state]);
}
