// Copyright (c) 2017, 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/services/correction/strings.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/generated/source.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';

const WIDGETS_LIBRARY_URI = 'package:flutter/widgets.dart';

const _BASIC_URI = "package:flutter/src/widgets/basic.dart";
const _CENTER_NAME = "Center";
const _CONTAINER_NAME = "Container";
const _CONTAINER_URI = "package:flutter/src/widgets/container.dart";
const _PADDING_NAME = "Padding";
const _STATE_NAME = "State";
const _STATEFUL_WIDGET_NAME = "StatefulWidget";
const _STATELESS_WIDGET_NAME = "StatelessWidget";
const _STREAM_BUILDER_NAME = "StreamBuilder";
const _STREAM_BUILDER_URI = "package:flutter/src/widgets/async.dart";
const _WIDGET_NAME = "Widget";
const _WIDGET_URI = "package:flutter/src/widgets/framework.dart";
final _frameworkUri = Uri.parse('package:flutter/src/widgets/framework.dart');

void convertChildToChildren(
    InstanceCreationExpression childArg,
    NamedExpression namedExp,
    String eol,
    Function getNodeText,
    Function getLinePrefix,
    Function getIndent,
    Function getText,
    Function _addInsertEdit,
    Function _addRemoveEdit,
    Function _addReplaceEdit,
    Function rangeNode) {
  int childLoc = namedExp.offset + 'child'.length;
  _addInsertEdit(childLoc, 'ren');
  int listLoc = childArg.offset;
  String childArgSrc = getNodeText(childArg);
  if (!childArgSrc.contains(eol)) {
    _addInsertEdit(listLoc, '<Widget>[');
    _addInsertEdit(listLoc + childArg.length, ']');
  } else {
    int newlineLoc = childArgSrc.lastIndexOf(eol);
    if (newlineLoc == childArgSrc.length) {
      newlineLoc -= 1;
    }
    String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
    String indentNew = '$indentOld${getIndent(1)}';
    // The separator includes 'child:' but that has no newlines.
    String separator =
        getText(namedExp.offset, childArg.offset - namedExp.offset);
    String prefix = separator.contains(eol) ? "" : "$eol$indentNew";
    if (prefix.isEmpty) {
      _addInsertEdit(namedExp.offset + 'child:'.length, ' <Widget>[');
      _addRemoveEdit(new SourceRange(childArg.offset - 2, 2));
    } else {
      _addInsertEdit(listLoc, '<Widget>[');
    }
    String newChildArgSrc = childArgSrc.replaceAll(
        new RegExp("^$indentOld", multiLine: true), "$indentNew");
    newChildArgSrc = "$prefix$newChildArgSrc,$eol$indentOld]";
    _addReplaceEdit(rangeNode(childArg), newChildArgSrc);
  }
}

void convertChildToChildren2(
    DartFileEditBuilder builder,
    Expression childArg,
    NamedExpression namedExp,
    String eol,
    Function getNodeText,
    Function getLinePrefix,
    Function getIndent,
    Function getText,
    Function rangeNode) {
  int childLoc = namedExp.offset + 'child'.length;
  builder.addSimpleInsertion(childLoc, 'ren');
  int listLoc = childArg.offset;
  String childArgSrc = getNodeText(childArg);
  if (!childArgSrc.contains(eol)) {
    builder.addSimpleInsertion(listLoc, '<Widget>[');
    builder.addSimpleInsertion(listLoc + childArg.length, ']');
  } else {
    int newlineLoc = childArgSrc.lastIndexOf(eol);
    if (newlineLoc == childArgSrc.length) {
      newlineLoc -= 1;
    }
    String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
    String indentNew = '$indentOld${getIndent(1)}';
    // The separator includes 'child:' but that has no newlines.
    String separator =
        getText(namedExp.offset, childArg.offset - namedExp.offset);
    String prefix = separator.contains(eol) ? "" : "$eol$indentNew";
    if (prefix.isEmpty) {
      builder.addSimpleInsertion(
          namedExp.offset + 'child:'.length, ' <Widget>[');
      builder.addDeletion(new SourceRange(childArg.offset - 2, 2));
    } else {
      builder.addSimpleInsertion(listLoc, '<Widget>[');
    }
    String newChildArgSrc = childArgSrc.replaceAll(
        new RegExp("^$indentOld", multiLine: true), "$indentNew");
    newChildArgSrc = "$prefix$newChildArgSrc,$eol$indentOld]";
    builder.addSimpleReplacement(rangeNode(childArg), newChildArgSrc);
  }
}

/**
 * Return the named expression representing the `child` argument of the given
 * [newExpr], or `null` if none.
 */
NamedExpression findChildArgument(InstanceCreationExpression newExpr) =>
    newExpr.argumentList.arguments
        .firstWhere(isChildArgument, orElse: () => null);

/**
 * Return the named expression representing the `children` argument of the
 * given [newExpr], or `null` if none.
 */
NamedExpression findChildrenArgument(InstanceCreationExpression newExpr) =>
    newExpr.argumentList.arguments
        .firstWhere(isChildrenArgument, orElse: () => null);

/**
 * Return the Flutter instance creation expression that is the value of the
 * 'child' argument of the given [newExpr], or null if none.
 */
InstanceCreationExpression findChildWidget(InstanceCreationExpression newExpr) {
  NamedExpression child = findChildArgument(newExpr);
  return getChildWidget(child);
}

/**
 * If the given [node] is a simple identifier, find the named expression whose
 * name is the given [name] that is an argument to a Flutter instance creation
 * expression. Return null if any condition cannot be satisfied.
 */
NamedExpression findNamedExpression(AstNode node, String name) {
  if (node is! SimpleIdentifier) {
    return null;
  }
  SimpleIdentifier namedArg = node;
  NamedExpression namedExp;
  if (namedArg.parent is Label && namedArg.parent.parent is NamedExpression) {
    namedExp = namedArg.parent.parent;
    if (namedArg.name != name || namedExp.expression == null) {
      return null;
    }
  } else {
    return null;
  }
  if (namedExp.parent?.parent is! InstanceCreationExpression) {
    return null;
  }
  InstanceCreationExpression newExpr = namedExp.parent.parent;
  if (newExpr == null || !isWidgetCreation(newExpr)) {
    return null;
  }
  return namedExp;
}

/**
 * Return the expression that is a Flutter Widget that is the value of the
 * given [child], or null if none.
 */
Expression getChildWidget(NamedExpression child) {
  Expression expression = child?.expression;
  if (isWidgetExpression(expression)) {
    return expression;
  }
  return null;
}

/**
 * Return the presentation for the given Flutter `Widget` creation [node].
 */
String getWidgetPresentationText(InstanceCreationExpression node) {
  ClassElement element = node.staticElement?.enclosingElement;
  if (!isWidget(element)) {
    return null;
  }
  List<Expression> arguments = node.argumentList.arguments;
  if (_isExactWidget(
      element, 'Icon', 'package:flutter/src/widgets/icon.dart')) {
    if (arguments.isNotEmpty) {
      String text = arguments[0].toString();
      String arg = shorten(text, 32);
      return 'Icon($arg)';
    } else {
      return 'Icon';
    }
  }
  if (_isExactWidget(
      element, 'Text', 'package:flutter/src/widgets/text.dart')) {
    if (arguments.isNotEmpty) {
      String text = arguments[0].toString();
      String arg = shorten(text, 32);
      return 'Text($arg)';
    } else {
      return 'Text';
    }
  }
  return element.name;
}

/**
 * Return the instance creation expression that surrounds the given
 * [node], if any, else null. The [node] may be the instance creation
 * expression itself or the identifier that names the constructor.
 */
InstanceCreationExpression identifyNewExpression(AstNode node) {
  InstanceCreationExpression newExpr;
  if (node is SimpleIdentifier) {
    if (node.parent is ConstructorName &&
        node.parent.parent is InstanceCreationExpression) {
      newExpr = node.parent.parent;
    } else if (node.parent?.parent is ConstructorName &&
        node.parent.parent?.parent is InstanceCreationExpression) {
      newExpr = node.parent.parent.parent;
    }
  } else if (node is InstanceCreationExpression) {
    newExpr = node;
  }
  return newExpr;
}

/**
 * Attempt to find and return the closest expression that encloses the [node]
 * and is an independent Flutter `Widget`.  Return `null` if nothing found.
 */
Expression identifyWidgetExpression(AstNode node) {
  for (; node != null; node = node.parent) {
    if (isWidgetExpression(node)) {
      var parent = node.parent;
      if (parent is ArgumentList ||
          parent is ListLiteral ||
          parent is NamedExpression && parent.expression == node ||
          parent is Statement) {
        return node;
      }
    }
    if (node is ArgumentList || node is Statement || node is FunctionBody) {
      return null;
    }
  }
  return null;
}

/**
 * Return `true` is the given [argument] is the `child` argument.
 */
bool isChildArgument(Expression argument) =>
    argument is NamedExpression && argument.name.label.name == 'child';

/**
 * Return `true` is the given [argument] is the `child` argument.
 */
bool isChildrenArgument(Expression argument) =>
    argument is NamedExpression && argument.name.label.name == 'children';

/**
 * Return `true` if the given [type] is the Flutter class `StatefulWidget`.
 */
bool isExactlyStatefulWidgetType(DartType type) {
  return type is InterfaceType &&
      _isExactWidget(type.element, _STATEFUL_WIDGET_NAME, _WIDGET_URI);
}

/**
 * Return `true` if the given [type] is the Flutter class `StatelessWidget`.
 */
bool isExactlyStatelessWidgetType(DartType type) {
  return type is InterfaceType &&
      _isExactWidget(type.element, _STATELESS_WIDGET_NAME, _WIDGET_URI);
}

/// Return `true` if the given [element] is the Flutter class `State`.
bool isExactState(ClassElement element) {
  return _isExactWidget(element, _STATE_NAME, _WIDGET_URI);
}

/**
 * Return `true` if the given [type] is the Flutter class `Center`.
 */
bool isExactWidgetTypeCenter(DartType type) {
  return type is InterfaceType &&
      _isExactWidget(type.element, _CENTER_NAME, _BASIC_URI);
}

/**
 * Return `true` if the given [type] is the Flutter class `Container`.
 */
bool isExactWidgetTypeContainer(DartType type) {
  return type is InterfaceType &&
      _isExactWidget(type.element, _CONTAINER_NAME, _CONTAINER_URI);
}

/**
 * Return `true` if the given [type] is the Flutter class `Padding`.
 */
bool isExactWidgetTypePadding(DartType type) {
  return type is InterfaceType &&
      _isExactWidget(type.element, _PADDING_NAME, _BASIC_URI);
}

/**
 * Return `true` if the given [type] is the Flutter class `StreamBuilder`.
 */
bool isExactWidgetTypeStreamBuilder(DartType type) {
  return type is InterfaceType &&
      _isExactWidget(type.element, _STREAM_BUILDER_NAME, _STREAM_BUILDER_URI);
}

/**
 * Return `true` if the given [type] is the Flutter class `Widget`, or its
 * subtype.
 */
bool isListOfWidgetsType(DartType type) {
  return type is InterfaceType &&
      type.element.library.isDartCore &&
      type.element.name == 'List' &&
      type.typeArguments.length == 1 &&
      isWidgetType(type.typeArguments[0]);
}

/// Return `true` if the given [element] has the Flutter class `State` as
/// a superclass.
bool isState(ClassElement element) {
  return _hasSupertype(element, _frameworkUri, _STATE_NAME);
}

/**
 * Return `true` if the given [element] is a [ClassElement] that extends
 * the Flutter class `StatefulWidget`.
 */
bool isStatefulWidgetDeclaration(Element element) {
  if (element is ClassElement) {
    return isExactlyStatefulWidgetType(element.supertype);
  }
  return false;
}

/**
 * Return `true` if the given [element] is the Flutter class `Widget`, or its
 * subtype.
 */
bool isWidget(ClassElement element) {
  if (element == null) {
    return false;
  }
  if (_isExactWidget(element, _WIDGET_NAME, _WIDGET_URI)) {
    return true;
  }
  for (InterfaceType type in element.allSupertypes) {
    if (_isExactWidget(type.element, _WIDGET_NAME, _WIDGET_URI)) {
      return true;
    }
  }
  return false;
}

/**
 * Return `true` if the given [expr] is a constructor invocation for a
 * class that has the Flutter class `Widget` as a superclass.
 */
bool isWidgetCreation(InstanceCreationExpression expr) {
  ClassElement element = expr?.staticElement?.enclosingElement;
  return isWidget(element);
}

/**
 * Return `true` if the given [node] is the Flutter class `Widget`, or its
 * subtype.
 */
bool isWidgetExpression(AstNode node) {
  if (node == null) {
    return false;
  }
  if (node.parent is TypeName || node.parent?.parent is TypeName) {
    return false;
  }
  if (node.parent is ConstructorName) {
    return false;
  }
  if (node is NamedExpression) {
    return false;
  }
  if (node is Expression) {
    return isWidgetType(node.staticType);
  }
  return false;
}

/**
 * Return `true` if the given [type] is the Flutter class `Widget`, or its
 * subtype.
 */
bool isWidgetType(DartType type) {
  return type is InterfaceType && isWidget(type.element);
}

/// Return `true` if the given [element] has a supertype with the [requiredName]
/// defined in the file with the [requiredUri].
bool _hasSupertype(ClassElement element, Uri requiredUri, String requiredName) {
  if (element == null) {
    return false;
  }
  for (InterfaceType type in element.allSupertypes) {
    if (type.name == requiredName) {
      Uri uri = type.element.source.uri;
      if (uri == requiredUri) {
        return true;
      }
    }
  }
  return false;
}

/**
 * Return `true` if the given [element] is the exact [type] defined in the
 * file with the given [uri].
 */
bool _isExactWidget(ClassElement element, String type, String uri) {
  return element != null &&
      element.name == type &&
      element.source.uri.toString() == uri;
}
