// 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 'package:build_daemon/client.dart';
import 'package:build_daemon/constants.dart' as daemon;
import 'package:build_daemon/data/build_status.dart';
import 'package:build_daemon/data/build_target.dart';
import 'package:build_daemon/data/server_log.dart';
import 'package:path/path.dart' as path; // ignore: package_path_import

import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../build_info.dart';
import '../cache.dart';
import '../dart/pub.dart';
import '../globals.dart' as globals;
import '../platform_plugins.dart';
import '../plugins.dart';
import '../project.dart';
import '../web/compile.dart';

/// A build_runner specific implementation of the [WebCompilationProxy].
class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
  BuildRunnerWebCompilationProxy();

  @override
  Future<bool> initialize({
    Directory projectDirectory,
    String testOutputDir,
    List<String> testFiles,
    BuildMode mode,
    String projectName,
    bool initializePlatform,
  }) async {
    // Create the .dart_tool directory if it doesn't exist.
    projectDirectory
      .childDirectory('.dart_tool')
      .createSync();
    final FlutterProject flutterProject = FlutterProject.fromDirectory(projectDirectory);
    final bool hasWebPlugins = (await findPlugins(flutterProject))
      .any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
    final BuildDaemonClient client = await const BuildDaemonCreator().startBuildDaemon(
      projectDirectory.path,
      release: mode == BuildMode.release,
      profile: mode == BuildMode.profile,
      hasPlugins: hasWebPlugins,
      initializePlatform: initializePlatform,
      testTargets: WebTestTargetManifest(
        testFiles
          .map<String>((String absolutePath) {
            final String relativePath = path.relative(absolutePath, from: projectDirectory.path);
            return '${path.withoutExtension(relativePath)}.*';
          })
          .toList(),
      ),
    );
    client.startBuild();
    bool success = true;
    await for (final BuildResults results in client.buildResults) {
      final BuildResult result = results.results.firstWhere((BuildResult result) {
        return result.target == 'web';
      }, orElse: () {
        // Assume build failed if we lack any results.
        return DefaultBuildResult((DefaultBuildResultBuilder b) => b.status == BuildStatus.failed);
      });
      if (result.status == BuildStatus.failed) {
        success = false;
        break;
      }
      if (result.status == BuildStatus.succeeded) {
        break;
      }
    }
    if (!success || testOutputDir == null) {
      return success;
    }
    final Directory rootDirectory = projectDirectory
      .childDirectory('.dart_tool')
      .childDirectory('build')
      .childDirectory('flutter_web');

    final Iterable<Directory> childDirectories = rootDirectory
      .listSync()
      .whereType<Directory>();
    for (final Directory childDirectory in childDirectories) {
      final String path = globals.fs.path.join(
        testOutputDir,
        'packages',
        globals.fs.path.basename(childDirectory.path),
      );
      globals.fsUtils.copyDirectorySync(
        childDirectory.childDirectory('lib'),
        globals.fs.directory(path),
      );
    }
    final Directory outputDirectory = rootDirectory
      .childDirectory(projectName)
      .childDirectory('test');
    globals.fsUtils.copyDirectorySync(
      outputDirectory,
      globals.fs.directory(globals.fs.path.join(testOutputDir)),
    );
    return success;
  }
}

class WebTestTargetManifest {
  WebTestTargetManifest(this.buildFilters);

  WebTestTargetManifest.all() : buildFilters = null;

  final List<String> buildFilters;

  bool get hasBuildFilters => buildFilters != null && buildFilters.isNotEmpty;
}

/// A testable interface for starting a build daemon.
class BuildDaemonCreator {
  const BuildDaemonCreator();

  // TODO(jonahwilliams): find a way to get build checks working for flutter for web.
  static const String _ignoredLine1 = 'Warning: Interpreting this as package URI';
  static const String _ignoredLine2 = 'build_script.dart was not found in the asset graph, incremental builds will not work';
  static const String _ignoredLine3 = 'have your dependencies specified fully in your pubspec.yaml';

  /// Start a build daemon and register the web targets.
  ///
  /// [initializePlatform] controls whether we should invoke [webOnlyInitializePlatform].
  Future<BuildDaemonClient> startBuildDaemon(String workingDirectory, {
    bool release = false,
    bool profile = false,
    bool hasPlugins = false,
    bool initializePlatform = true,
    WebTestTargetManifest testTargets,
  }) async {
    try {
      final BuildDaemonClient client = await _connectClient(
        workingDirectory,
        release: release,
        profile: profile,
        hasPlugins: hasPlugins,
        initializePlatform: initializePlatform,
        testTargets: testTargets,
      );
      _registerBuildTargets(client, testTargets);
      return client;
    } on OptionsSkew {
      throwToolExit(
        'Incompatible options with current running build daemon.\n\n'
        'Please stop other flutter_tool instances running in this directory '
        'before starting a new instance with these options.'
      );
    }
    return null;
  }

  void _registerBuildTargets(
    BuildDaemonClient client,
    WebTestTargetManifest testTargets,
  ) {
    final OutputLocation outputLocation = OutputLocation((OutputLocationBuilder b) => b
      ..output = ''
      ..useSymlinks = true
      ..hoist = false);
    client.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder b) => b
      ..target = 'web'
      ..outputLocation = outputLocation?.toBuilder()));
    if (testTargets != null) {
      client.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder b) {
        b.target = 'test';
        b.outputLocation = outputLocation?.toBuilder();
        if (testTargets.hasBuildFilters) {
          b.buildFilters.addAll(testTargets.buildFilters);
        }
      }));
    }
  }

  Future<BuildDaemonClient> _connectClient(
    String workingDirectory, {
    bool release,
    bool profile,
    bool hasPlugins,
    bool initializePlatform,
    WebTestTargetManifest testTargets,
  }) async {
    // The build script is stored in an auxiliary package to reduce
    // dependencies of the main tool.
    final String buildScriptPackages = globals.fs.path.join(
      Cache.flutterRoot,
      'packages',
      '_flutter_web_build_script',
      '.packages',
    );
    final String buildScript = globals.fs.path.join(
      Cache.flutterRoot,
      'packages',
      '_flutter_web_build_script',
      'lib',
      'build_script.dart',
    );
    if (!globals.fs.isFileSync(buildScript)) {
      throwToolExit('Expected a file $buildScript to exist in the Flutter SDK.');
    }
    // If we're missing the .packages file, perform a pub get.
    if (!globals.fs.isFileSync(buildScriptPackages)) {
      await pub.get(
        context: PubContext.pubGet,
        directory: globals.fs.file(buildScriptPackages).parent.path,
        generateSyntheticPackage: false,
      );
    }
    final String flutterWebSdk = globals.artifacts.getArtifactPath(Artifact.flutterWebSdk);

    // On Windows we need to call the snapshot directly otherwise
    // the process will start in a disjoint cmd without access to
    // STDIO.
    final List<String> args = <String>[
      globals.artifacts.getArtifactPath(Artifact.engineDartBinary),
      '--disable-dart-dev',
      '--packages=$buildScriptPackages',
      buildScript,
      'daemon',
      '--enable-experiment=non-nullable',
      '--skip-build-script-check',
      '--define', 'flutter_tools:ddc=flutterWebSdk=$flutterWebSdk',
      // The following will cause build runner to only build tests that were requested.
      if (testTargets != null && testTargets.hasBuildFilters)
        for (final String buildFilter in testTargets.buildFilters)
          '--build-filter=$buildFilter',
    ];

    return BuildDaemonClient.connect(
      workingDirectory,
      args,
      logHandler: (ServerLog serverLog) {
        switch (serverLog.level) {
          case Level.SEVERE:
          case Level.SHOUT:
            // Ignore certain non-actionable messages on startup.
            if (serverLog.message.contains(_ignoredLine1) ||
                serverLog.message.contains(_ignoredLine2) ||
                serverLog.message.contains(_ignoredLine3)) {
              return;
            }
            globals.printError(serverLog.message);
            if (serverLog.error != null) {
              globals.printError(serverLog.error);
            }
            if (serverLog.stackTrace != null) {
              globals.printTrace(serverLog.stackTrace);
            }
            break;
          default:
            if (serverLog.message.contains('Skipping compiling')) {
              globals.printError(serverLog.message);
            } else {
              globals.printTrace(serverLog.message);
            }
        }
      },
      buildMode: daemon.BuildMode.Manual,
    );
  }
}
