// 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: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';

const _FLUTTER_WIDGET_NAME = "Widget";
const _FLUTTER_WIDGET_URI = "package:flutter/src/widgets/framework.dart";

void convertFlutterChildToChildren(
    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);
  }
}

/**
 * Return the named expression representing the 'child' argument of the given
 * [newExpr], or null if none.
 */
NamedExpression findChildArgument(InstanceCreationExpression newExpr) =>
    newExpr.argumentList.arguments.firstWhere(
        (arg) => arg is NamedExpression && arg.name.label.name == 'child',
        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 findFlutterNamedExpression(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 || !isFlutterInstanceCreationExpression(newExpr)) {
    return null;
  }
  return namedExp;
}

ListLiteral getChildList(NamedExpression child) {
  if (child.expression is ListLiteral) {
    ListLiteral list = child.expression;
    if (list.elements.isEmpty ||
        list.elements.every((element) =>
            element is InstanceCreationExpression &&
            isFlutterInstanceCreationExpression(element))) {
      return list;
    }
  }
  return null;
}

/**
 * Return the Flutter instance creation expression that is the value of the
 * given [child], or null if none. If [strict] is true, require the value to
 * also have a 'child' argument.
 */
InstanceCreationExpression getChildWidget(NamedExpression child,
    [bool strict = false]) {
  if (child?.expression is InstanceCreationExpression) {
    InstanceCreationExpression childNewExpr = child.expression;
    if (isFlutterInstanceCreationExpression(childNewExpr)) {
      if (!strict || (findChildArgument(childNewExpr) != null)) {
        return childNewExpr;
      }
    }
  }
  return null;
}

/**
 * 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;
}

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

/**
 * Return `true` if the given [classElement] has the Flutter class Widget as a
 * superclass.
 */
bool isFlutterWidget(ClassElement classElement) {
  InterfaceType superType = classElement?.allSupertypes?.firstWhere(
      (InterfaceType type) => _FLUTTER_WIDGET_NAME == type.name,
      orElse: () => null);
  if (superType == null) {
    return false;
  }
  Uri uri = superType.element?.source?.uri;
  if (uri.toString() != _FLUTTER_WIDGET_URI) {
    return false;
  }
  return true;
}
