// Copyright 2023 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.

import 'dart:io';

import 'package:args/command_runner.dart';
import 'package:devtools_tool/commands/shared.dart';
import 'package:devtools_tool/model.dart';
import 'package:io/io.dart';
import 'package:path/path.dart' as path;

import '../utils.dart';

/// This command builds the DevTools Flutter web app.
///
/// By default, this command builds DevTools in release mode, but this can be
/// overridden by passing 'debug' or 'profile' as the
/// [SharedCommandArgs.buildMode] argument. For testing embedded content in
/// VS Code, 'profile' or the default 'release' mode must be used because
/// the '--dart2js-optimization=O1' flag that is passed for 'debug' builds
/// will cause issues with the VS Code embedding.
///
/// If the [SharedCommandArgs.useFlutterFromPath] argument is present, the
/// Flutter SDK will not be updated to the latest Flutter candidate before
/// building DevTools. Use this flag to save the cost of updating the Flutter
/// SDK when you already have the proper SDK checked out. This is helpful when
/// developing with the DevTools server.
///
/// If the [SharedCommandArgs.updatePerfetto] argument is present, the
/// precompiled bits for Perfetto will be updated from the
/// `dt update-perfetto` command as part of the DevTools build
/// process.
///
/// If [SharedCommandArgs.pubGet] argument is negated (e.g. --no-pub-get), then
/// `dt pub-get --only-main` command will not be run before building
/// the DevTools web app. Use this flag to save the cost of updating pub
/// packages if your pub cahce does not need to be updated. This is helpful when
/// developing with the DevTools server.
class BuildCommand extends Command {
  BuildCommand() {
    argParser
      ..addUpdateFlutterFlag()
      ..addUpdatePerfettoFlag()
      ..addPubGetFlag()
      ..addBulidModeOption()
      ..addWasmFlag()
      ..addNoStripWasmFlag()
      ..addNoMinifyWasmFlag();
  }

  @override
  String get name => 'build';

  @override
  String get description => 'Prepares a release build of DevTools.';

  @override
  Future run() async {
    final repo = DevToolsRepo.getInstance();
    final processManager = ProcessManager();
    final results = argResults!;
    final updateFlutter =
        results[SharedCommandArgs.updateFlutter.flagName] as bool;
    final updatePerfetto =
        results[SharedCommandArgs.updatePerfetto.flagName] as bool;
    final runPubGet = results[SharedCommandArgs.pubGet.flagName] as bool;
    final buildMode = results[SharedCommandArgs.buildMode.flagName] as String;
    final useWasm = results[SharedCommandArgs.wasm.flagName] as bool;
    final noStripWasm = results[SharedCommandArgs.noStripWasm.flagName] as bool;
    final noMinifyWasm =
        results[SharedCommandArgs.noMinifyWasm.flagName] as bool;

    final webBuildDir = Directory(
      path.join(repo.devtoolsAppDirectoryPath, 'build', 'web'),
    );

    if (updateFlutter) {
      logStatus('updating tool/flutter-sdk to the latest flutter candidate');
      await processManager.runProcess(CliCommand.tool(['update-flutter-sdk']));
    }

    if (updatePerfetto) {
      logStatus('updating the bundled Perfetto assets');
      await processManager.runProcess(CliCommand.tool(['update-perfetto']));
    }

    logStatus('cleaning project');
    if (webBuildDir.existsSync()) {
      webBuildDir.deleteSync(recursive: true);
    }
    await processManager.runProcess(
      CliCommand.flutter(['clean']),
      workingDirectory: repo.devtoolsAppDirectoryPath,
    );

    logStatus(
      'building DevTools in $buildMode mode with '
      '${useWasm ? 'dart2wasm' : 'dart2js'}',
    );
    await processManager.runAll(
      commands: [
        if (runPubGet) CliCommand.tool(['pub-get', '--only-main']),
        CliCommand.flutter([
          'build',
          'web',
          '--source-maps',
          if (useWasm) ...[
            SharedCommandArgs.wasm.asArg(),
            if (noStripWasm) SharedCommandArgs.noStripWasm.asArg(),
            if (noMinifyWasm) SharedCommandArgs.noMinifyWasm.asArg(),
          ] else ...[
            // Do not minify stack traces in debug mode.
            if (buildMode == 'debug') '--dart2js-optimization=O1',
            if (buildMode != 'debug') '--$buildMode',
          ],
          '--pwa-strategy=offline-first',
          '--no-tree-shake-icons',
        ]),
      ],
      workingDirectory: repo.devtoolsAppDirectoryPath,
    );

    // TODO(kenz): investigate if we need to perform a windows equivalent of
    // `chmod` or if we even need to perform `chmod` for linux / mac anymore.
    if (!Platform.isWindows) {
      final canvaskitDir = Directory(path.join(webBuildDir.path, 'canvaskit'));
      for (final file in canvaskitDir.listSync()) {
        if (RegExp(r'canvaskit\..*').hasMatch(file.path)) {
          await processManager.runProcess(
            CliCommand('chmod', ['0755', file.path]),
          );
        }
      }
    }
  }
}
