// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

import 'package:path/path.dart' as path;

import '../framework/devices.dart';
import '../framework/framework.dart';
import '../framework/task_result.dart';
import '../framework/utils.dart';

const String _packageName = 'package_with_native_assets';

const List<String> _buildModes = <String>[
  'debug',
  'profile',
  'release',
];

TaskFunction createNativeAssetsTest({
  String? deviceIdOverride,
  bool checkAppRunningOnLocalDevice = true,
  bool isIosSimulator = false,
}) {
  return () async {
    if (deviceIdOverride == null) {
      final Device device = await devices.workingDevice;
      await device.unlock();
      deviceIdOverride = device.deviceId;
    }

    await enableNativeAssets();

    for (final String buildMode in _buildModes) {
      if (buildMode != 'debug' && isIosSimulator) {
        continue;
      }
      final TaskResult buildModeResult = await inTempDir((Directory tempDirectory) async {
        final Directory packageDirectory = await createTestProject(_packageName, tempDirectory);
        final Directory exampleDirectory = dir(packageDirectory.uri.resolve('example/').toFilePath());

        final List<String> options = <String>[
          '-d',
          deviceIdOverride!,
          '--no-android-gradle-daemon',
          '--no-publish-port',
          '--verbose',
          '--uninstall-first',
          '--$buildMode',
        ];
        int transitionCount = 0;
        bool done = false;

        await inDirectory<void>(exampleDirectory, () async {
          final int runFlutterResult = await runFlutter(
            options: options,
            onLine: (String line, Process process) {
              if (done) {
                return;
              }
              switch (transitionCount) {
                case 0:
                  if (!line.contains('Flutter run key commands.')) {
                    return;
                  }
                  if (buildMode == 'debug') {
                    // Do a hot reload diff on the initial dill file.
                    process.stdin.writeln('r');
                  } else {
                    done = true;
                    process.stdin.writeln('q');
                  }
                case 1:
                  if (!line.contains('Reloaded')) {
                    return;
                  }
                  process.stdin.writeln('R');
                case 2:
                  // Do a hot restart, pushing a new complete dill file.
                  if (!line.contains('Restarted application')) {
                    return;
                  }
                  // Do another hot reload, pushing a diff to the second dill file.
                  process.stdin.writeln('r');
                case 3:
                  if (!line.contains('Reloaded')) {
                    return;
                  }
                  done = true;
                  process.stdin.writeln('q');
              }
              transitionCount += 1;
            },
          );
          if (runFlutterResult != 0) {
            print('Flutter run returned non-zero exit code: $runFlutterResult.');
          }
        });

        final int expectedNumberOfTransitions = buildMode == 'debug' ? 4 : 1;
        if (transitionCount != expectedNumberOfTransitions) {
          return TaskResult.failure(
            'Did not get expected number of transitions: $transitionCount '
            '(expected $expectedNumberOfTransitions)',
          );
        }
        return TaskResult.success(null);
      });
      if (buildModeResult.failed) {
        return buildModeResult;
      }
    }
    return TaskResult.success(null);
  };
}

Future<int> runFlutter({
  required List<String> options,
  required void Function(String, Process) onLine,
}) async {
  final Process process = await startFlutter(
    'run',
    options: options,
  );

  final Completer<void> stdoutDone = Completer<void>();
  final Completer<void> stderrDone = Completer<void>();
  process.stdout.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen((String line) {
    onLine(line, process);
    print('stdout: $line');
  }, onDone: stdoutDone.complete);

  process.stderr.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen(
        (String line) => print('stderr: $line'),
        onDone: stderrDone.complete,
      );

  await Future.wait<void>(<Future<void>>[stdoutDone.future, stderrDone.future]);
  final int exitCode = await process.exitCode;
  return exitCode;
}

final String _flutterBin = path.join(flutterDirectory.path, 'bin', 'flutter');

Future<void> enableNativeAssets() async {
  print('Enabling configs for native assets...');
  final int configResult = await exec(
      _flutterBin,
      <String>[
        'config',
        '-v',
        '--enable-native-assets',
      ],
      canFail: true);
  if (configResult != 0) {
    print('Failed to enable configuration, tasks may not run.');
  }
}

Future<Directory> createTestProject(
  String packageName,
  Directory tempDirectory,
) async {
  await exec(
    _flutterBin,
    <String>[
      'create',
      '--no-pub',
      '--template=package_ffi',
      packageName,
    ],
    workingDirectory: tempDirectory.path,
  );

  final Directory packageDirectory = Directory(
    path.join(tempDirectory.path, packageName),
  );
  await _pinDependencies(
    File(path.join(packageDirectory.path, 'pubspec.yaml')),
  );
  await _pinDependencies(
    File(path.join(packageDirectory.path, 'example', 'pubspec.yaml')),
  );

  await exec(
    _flutterBin,
    <String>[
      'pub',
      'get',
    ],
    workingDirectory: packageDirectory.path,
  );

  return packageDirectory;
}

Future<void> _pinDependencies(File pubspecFile) async {
  final String oldPubspec = await pubspecFile.readAsString();
  final String newPubspec = oldPubspec.replaceAll(': ^', ': ');
  await pubspecFile.writeAsString(newPubspec);
}


Future<T> inTempDir<T>(Future<T> Function(Directory tempDirectory) fun) async {
  final Directory tempDirectory = dir(Directory.systemTemp.createTempSync().resolveSymbolicLinksSync());
  try {
    return await fun(tempDirectory);
  } finally {
    tempDirectory.deleteSync(recursive: true);
  }
}
