// 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.

// See http://dartbug.com/33660 for details about what inspired this generator.

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

Random random = new Random();
int totalNodes = 0;
Set<String> seen = new Set<String>();

main(List<String> args) async {
  int maxSize;
  if (args.length > 0) maxSize = int.tryParse(args[0]);
  maxSize ??= 5;

  for (int i = 0; i < 2500; i++) {
    stdout.write(".");
    if (i % 75 == 74) stdout.write("\n");
    totalNodes = 0;
    Tree tree = fuzz(1 + random.nextInt(5), 1 + random.nextInt(8), maxSize);
    String expected =
        new List<String>.generate(totalNodes, (i) => "${i + 1}").join(" ");
    String asyncProgram = printProgram(tree, true, false, true, '"$expected"');
    if (seen.add(asyncProgram)) {
      File asyncFile = new File('${maxSize}_${i}.dart')
        ..writeAsStringSync(asyncProgram);

      List<String> run = await executeAndGetStdOut(
          Platform.executable, <String>[asyncFile.path]);
      if (expected == run[0]) {
        asyncFile.deleteSync();
      } else {
        print("\n${asyncFile.path} was not as expected!");
        String name = "async_nested_${maxSize}_${i}_test.dart";
        asyncFile.renameSync(name);
        print(" -> Created $name");
        print("    (you might want to run 'dart format $name').");
      }
    }
  }
  print(" done ");
}

Tree fuzz(int asyncLikely, int childrenLikely, int maxSize) {
  // asyncLikely = 3;
  // childrenLikely = 5;
  totalNodes++;
  Tree result = new Tree();
  result.name = "$totalNodes";
  result.async = random.nextInt(10) < asyncLikely;

  while (random.nextInt(10) < childrenLikely) {
    if (totalNodes >= maxSize) return result;
    result.children
        .add(fuzz(1 + random.nextInt(5), 1 + random.nextInt(8), maxSize));
  }

  return result;
}

String printProgram(Tree tree, bool emitAsync, bool emitPrintOnCreate,
    bool printSimple, String expected) {
  StringBuffer lines = new StringBuffer();
  lines.write("""
// 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.

// This has been automatically generated by script
// "async_nested_test_generator.dart".

import 'dart:async';

void main() async {
""");

  printNode(Tree node) {
    if (node.async && emitAsync) {
      lines.write("await new Future.value(");
    }
    lines.writeln("new Node('${node.name}', [");
    for (Tree child in node.children) {
      printNode(child);
      lines.write(",");
    }
    lines.writeln("])");
    if (node.async && emitAsync) {
      lines.write(")");
    }
  }

  if (expected != null) {
    lines.writeln('String expected = $expected;');
  }
  lines.write("Node node = ");
  printNode(tree);
  lines.writeln(";");
  if (printSimple) {
    lines.writeln("String actual = node.toSimpleString();");
  } else {
    lines.writeln("String actual = node.toString();");
  }
  lines.writeln("print(actual);");

  if (expected != null) {
    lines.writeln(r"""if (actual != expected) {
      throw "Expected '$expected' but got '$actual'";
    }""");
  }

  lines.writeln(r"""
}

class Node {
  final List<Node>? nested;
  final String name;

  Node(this.name, [this.nested]) {
""");
  if (emitPrintOnCreate) {
    lines.writeln(r'print("Creating $name");');
  }

  lines.write(r"""
  }

  String toString() => '<$name:[${nested?.join(', ')}]>';

  toSimpleString() {
    var tmp = nested?.map((child) => child.toSimpleString());
    return '$name ${tmp?.join(' ')}'.trim();
  }
}
""");

  return lines.toString();
}

Future<List<String>> executeAndGetStdOut(
    String executable, List<String> arguments) async {
  var process = await Process.start(executable, arguments);
  Future<List<String>> result = combine(
      process.stdout
          .transform(utf8.decoder)
          .transform(const LineSplitter())
          .toList(),
      process.stderr
          .transform(utf8.decoder)
          .transform(const LineSplitter())
          .toList());
  int exitCode = await process.exitCode;
  (await result).add("Exit code: $exitCode");

  return result;
}

Future<List<String>> combine(
    Future<List<String>> a, Future<List<String>> b) async {
  List<String> aDone = await a;
  List<String> bDone = await b;
  List<String> result = new List.from(aDone);
  result.addAll(bDone);
  return result;
}

class Tree {
  String name;
  bool async = false;
  List<Tree> children = <Tree>[];
}
