// 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';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.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);
  }
}

void convertFlutterChildToChildren2(
    DartFileEditBuilder builder,
    InstanceCreationExpression 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(
        (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;
}
