// Copyright 2013 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 'package:file/file.dart';
import 'package:platform/platform.dart';
import 'package:yaml/yaml.dart';

import 'common/core.dart';
import 'common/package_looping_command.dart';
import 'common/plugin_utils.dart';
import 'common/process_runner.dart';
import 'common/repository_package.dart';

/// Key for APK.
const String _platformFlagApk = 'apk';

const String _pluginToolsConfigFileName = '.pluginToolsConfig.yaml';
const String _pluginToolsConfigBuildFlagsKey = 'buildFlags';
const String _pluginToolsConfigGlobalKey = 'global';

const String _pluginToolsConfigExample = '''
$_pluginToolsConfigBuildFlagsKey:
  $_pluginToolsConfigGlobalKey:
    - "--no-tree-shake-icons"
    - "--dart-define=buildmode=testing"
''';

const int _exitNoPlatformFlags = 3;
const int _exitInvalidPluginToolsConfig = 4;

// Flutter build types. These are the values passed to `flutter build <foo>`.
const String _flutterBuildTypeAndroid = 'apk';
const String _flutterBuildTypeIOS = 'ios';
const String _flutterBuildTypeLinux = 'linux';
const String _flutterBuildTypeMacOS = 'macos';
const String _flutterBuildTypeWeb = 'web';
const String _flutterBuildTypeWindows = 'windows';

/// A command to build the example applications for packages.
class BuildExamplesCommand extends PackageLoopingCommand {
  /// Creates an instance of the build command.
  BuildExamplesCommand(
    Directory packagesDir, {
    ProcessRunner processRunner = const ProcessRunner(),
    Platform platform = const LocalPlatform(),
  }) : super(packagesDir, processRunner: processRunner, platform: platform) {
    argParser.addFlag(platformLinux);
    argParser.addFlag(platformMacOS);
    argParser.addFlag(platformWeb);
    argParser.addFlag(platformWindows);
    argParser.addFlag(platformIOS);
    argParser.addFlag(_platformFlagApk);
    argParser.addOption(
      kEnableExperiment,
      defaultsTo: '',
      help: 'Enables the given Dart SDK experiments.',
    );
  }

  // Maps the switch this command uses to identify a platform to information
  // about it.
  static final Map<String, _PlatformDetails> _platforms =
      <String, _PlatformDetails>{
    _platformFlagApk: const _PlatformDetails(
      'Android',
      pluginPlatform: platformAndroid,
      flutterBuildType: _flutterBuildTypeAndroid,
    ),
    platformIOS: const _PlatformDetails(
      'iOS',
      pluginPlatform: platformIOS,
      flutterBuildType: _flutterBuildTypeIOS,
      extraBuildFlags: <String>['--no-codesign'],
    ),
    platformLinux: const _PlatformDetails(
      'Linux',
      pluginPlatform: platformLinux,
      flutterBuildType: _flutterBuildTypeLinux,
    ),
    platformMacOS: const _PlatformDetails(
      'macOS',
      pluginPlatform: platformMacOS,
      flutterBuildType: _flutterBuildTypeMacOS,
    ),
    platformWeb: const _PlatformDetails(
      'web',
      pluginPlatform: platformWeb,
      flutterBuildType: _flutterBuildTypeWeb,
    ),
    platformWindows: const _PlatformDetails(
      'Windows',
      pluginPlatform: platformWindows,
      flutterBuildType: _flutterBuildTypeWindows,
    ),
  };

  @override
  final String name = 'build-examples';

  @override
  final String description =
      'Builds all example apps (IPA for iOS and APK for Android).\n\n'
      'This command requires "flutter" to be in your path.\n\n'
      'A $_pluginToolsConfigFileName file can be placed in an example app '
      'directory to specify additional build arguments. It should be a YAML '
      'file with a top-level map containing a single key '
      '"$_pluginToolsConfigBuildFlagsKey" containing a map containing a '
      'single key "$_pluginToolsConfigGlobalKey" containing a list of build '
      'arguments.';

  @override
  Future<void> initializeRun() async {
    final List<String> platformFlags = _platforms.keys.toList();
    platformFlags.sort();
    if (!platformFlags.any((String platform) => getBoolArg(platform))) {
      printError(
          'None of ${platformFlags.map((String platform) => '--$platform').join(', ')} '
          'were specified. At least one platform must be provided.');
      throw ToolExit(_exitNoPlatformFlags);
    }
  }

  @override
  Future<PackageResult> runForPackage(RepositoryPackage package) async {
    final List<String> errors = <String>[];

    final bool isPlugin = isFlutterPlugin(package);
    final Iterable<_PlatformDetails> requestedPlatforms = _platforms.entries
        .where(
            (MapEntry<String, _PlatformDetails> entry) => getBoolArg(entry.key))
        .map((MapEntry<String, _PlatformDetails> entry) => entry.value);

    // Platform support is checked at the package level for plugins; there is
    // no package-level platform information for non-plugin packages.
    final Set<_PlatformDetails> buildPlatforms = isPlugin
        ? requestedPlatforms
            .where((_PlatformDetails platform) =>
                pluginSupportsPlatform(platform.pluginPlatform, package))
            .toSet()
        : requestedPlatforms.toSet();

    String platformDisplayList(Iterable<_PlatformDetails> platforms) {
      return platforms.map((_PlatformDetails p) => p.label).join(', ');
    }

    if (buildPlatforms.isEmpty) {
      final String unsupported = requestedPlatforms.length == 1
          ? '${requestedPlatforms.first.label} is not supported'
          : 'None of [${platformDisplayList(requestedPlatforms)}] are supported';
      return PackageResult.skip('$unsupported by this plugin');
    }
    print('Building for: ${platformDisplayList(buildPlatforms)}');

    final Set<_PlatformDetails> unsupportedPlatforms =
        requestedPlatforms.toSet().difference(buildPlatforms);
    if (unsupportedPlatforms.isNotEmpty) {
      final List<String> skippedPlatforms = unsupportedPlatforms
          .map((_PlatformDetails platform) => platform.label)
          .toList();
      skippedPlatforms.sort();
      print('Skipping unsupported platform(s): '
          '${skippedPlatforms.join(', ')}');
    }
    print('');

    bool builtSomething = false;
    for (final RepositoryPackage example in package.getExamples()) {
      final String packageName =
          getRelativePosixPath(example.directory, from: packagesDir);

      for (final _PlatformDetails platform in buildPlatforms) {
        // Repo policy is that a plugin must have examples configured for all
        // supported platforms. For packages, just log and skip any requested
        // platform that a package doesn't have set up.
        if (!isPlugin &&
            !example.directory
                .childDirectory(platform.flutterPlatformDirectory)
                .existsSync()) {
          print('Skipping ${platform.label} for $packageName; not supported.');
          continue;
        }

        builtSomething = true;

        String buildPlatform = platform.label;
        if (platform.label.toLowerCase() != platform.flutterBuildType) {
          buildPlatform += ' (${platform.flutterBuildType})';
        }
        print('\nBUILDING $packageName for $buildPlatform');
        if (!await _buildExample(example, platform.flutterBuildType,
            extraBuildFlags: platform.extraBuildFlags)) {
          errors.add('$packageName (${platform.label})');
        }
      }
    }

    if (!builtSomething) {
      if (isPlugin) {
        errors.add('No examples found');
      } else {
        return PackageResult.skip(
            'No examples found supporting requested platform(s).');
      }
    }

    return errors.isEmpty
        ? PackageResult.success()
        : PackageResult.fail(errors);
  }

  Iterable<String> _readExtraBuildFlagsConfiguration(
      Directory directory) sync* {
    final File pluginToolsConfig =
        directory.childFile(_pluginToolsConfigFileName);
    if (pluginToolsConfig.existsSync()) {
      final Object? configuration =
          loadYaml(pluginToolsConfig.readAsStringSync());
      if (configuration is! YamlMap) {
        printError('The $_pluginToolsConfigFileName file must be a YAML map.');
        printError(
            'Currently, the key "$_pluginToolsConfigBuildFlagsKey" is the only one that has an effect.');
        printError(
            'It must itself be a map. Currently, in that map only the key "$_pluginToolsConfigGlobalKey"');
        printError(
            'has any effect; it must contain a list of arguments to pass to the');
        printError('flutter tool.');
        printError(_pluginToolsConfigExample);
        throw ToolExit(_exitInvalidPluginToolsConfig);
      }
      if (configuration.containsKey(_pluginToolsConfigBuildFlagsKey)) {
        final Object? buildFlagsConfiguration =
            configuration[_pluginToolsConfigBuildFlagsKey];
        if (buildFlagsConfiguration is! YamlMap) {
          printError(
              'The $_pluginToolsConfigFileName file\'s "$_pluginToolsConfigBuildFlagsKey" key must be a map.');
          printError(
              'Currently, in that map only the key "$_pluginToolsConfigGlobalKey" has any effect; it must ');
          printError(
              'contain a list of arguments to pass to the flutter tool.');
          printError(_pluginToolsConfigExample);
          throw ToolExit(_exitInvalidPluginToolsConfig);
        }
        if (buildFlagsConfiguration.containsKey(_pluginToolsConfigGlobalKey)) {
          final Object? globalBuildFlagsConfiguration =
              buildFlagsConfiguration[_pluginToolsConfigGlobalKey];
          if (globalBuildFlagsConfiguration is! YamlList) {
            printError(
                'The $_pluginToolsConfigFileName file\'s "$_pluginToolsConfigBuildFlagsKey" key must be a map');
            printError('whose "$_pluginToolsConfigGlobalKey" key is a list.');
            printError(
                'That list must contain a list of arguments to pass to the flutter tool.');
            printError(
                'For example, the $_pluginToolsConfigFileName file could look like:');
            printError(_pluginToolsConfigExample);
            throw ToolExit(_exitInvalidPluginToolsConfig);
          }
          yield* globalBuildFlagsConfiguration.cast<String>();
        }
      }
    }
  }

  Future<bool> _buildExample(
    RepositoryPackage example,
    String flutterBuildType, {
    List<String> extraBuildFlags = const <String>[],
  }) async {
    final String enableExperiment = getStringArg(kEnableExperiment);

    final int exitCode = await processRunner.runAndStream(
      flutterCommand,
      <String>[
        'build',
        flutterBuildType,
        ...extraBuildFlags,
        ..._readExtraBuildFlagsConfiguration(example.directory),
        if (enableExperiment.isNotEmpty)
          '--enable-experiment=$enableExperiment',
      ],
      workingDir: example.directory,
    );
    return exitCode == 0;
  }
}

/// A collection of information related to a specific platform.
class _PlatformDetails {
  const _PlatformDetails(
    this.label, {
    required this.pluginPlatform,
    required this.flutterBuildType,
    this.extraBuildFlags = const <String>[],
  });

  /// The name to use in output.
  final String label;

  /// The key in a pubspec's platform: entry.
  final String pluginPlatform;

  /// The `flutter build` build type.
  final String flutterBuildType;

  /// The Flutter platform directory name.
  // In practice, this is the same as the plugin platform key for all platforms.
  // If that changes, this can be adjusted.
  String get flutterPlatformDirectory => pluginPlatform;

  /// Any extra flags to pass to `flutter build`.
  final List<String> extraBuildFlags;
}
