// 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 'package:build_daemon/client.dart';
import 'package:build_daemon/data/build_status.dart';
import 'package:build_daemon/data/build_status.dart' as build;
import 'package:build_daemon/data/build_target.dart';
import 'package:build_daemon/data/server_log.dart';
import 'package:crypto/crypto.dart' show md5;
import 'package:yaml/yaml.dart';

import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../codegen.dart';
import '../dart/pub.dart';
import '../dart/sdk.dart';
import '../globals.dart' as globals;
import '../project.dart';

/// The minimum version of build_runner we can support in the flutter tool.
const String kMinimumBuildRunnerVersion = '1.7.1';
const String kSupportedBuildDaemonVersion = '2.1.0';

/// A wrapper for a build_runner process which delegates to a generated
/// build script.
///
/// This is only enabled if [experimentalBuildEnabled] is true, and only for
/// external flutter users.
class BuildRunner extends CodeGenerator {
  const BuildRunner();

  @override
  Future<void> generateBuildScript(FlutterProject flutterProject) async {
    final Directory entrypointDirectory = globals.fs.directory(globals.fs.path.join(flutterProject.dartTool.path, 'build', 'entrypoint'));
    final Directory generatedDirectory = globals.fs.directory(globals.fs.path.join(flutterProject.dartTool.path, 'flutter_tool'));
    final File buildSnapshot = entrypointDirectory.childFile('build.dart.snapshot');
    final File scriptIdFile = entrypointDirectory.childFile('id');
    final File syntheticPubspec = generatedDirectory.childFile('pubspec.yaml');

    // Check if contents of builders changed. If so, invalidate build script
    // and regenerate.
    final YamlMap builders = flutterProject.builders;
    final List<int> appliedBuilderDigest = _produceScriptId(builders);
    if (scriptIdFile.existsSync() && buildSnapshot.existsSync()) {
      final List<int> previousAppliedBuilderDigest = scriptIdFile.readAsBytesSync();
      bool digestsAreEqual = false;
      if (appliedBuilderDigest.length == previousAppliedBuilderDigest.length) {
        digestsAreEqual = true;
        for (int i = 0; i < appliedBuilderDigest.length; i++) {
          if (appliedBuilderDigest[i] != previousAppliedBuilderDigest[i]) {
            digestsAreEqual = false;
            break;
          }
        }
      }
      if (digestsAreEqual) {
        return;
      }
    }
    // Clean-up all existing artifacts.
    if (flutterProject.dartTool.existsSync()) {
      flutterProject.dartTool.deleteSync(recursive: true);
    }
    final Status status = globals.logger.startProgress('generating build script...', timeout: null);
    try {
      generatedDirectory.createSync(recursive: true);
      entrypointDirectory.createSync(recursive: true);
      flutterProject.dartTool.childDirectory('build').childDirectory('generated').createSync(recursive: true);
      final StringBuffer stringBuffer = StringBuffer();

      stringBuffer.writeln('name: flutter_tool');
      stringBuffer.writeln('dependencies:');
      final YamlMap builders = flutterProject.builders;
      if (builders != null) {
        for (final String name in builders.keys.cast<String>()) {
          final Object node = builders[name];
          // For relative paths, make sure it is accounted for
          // parent directories.
          if (node is YamlMap && node['path'] != null) {
            final String path = node['path'] as String;
            if (globals.fs.path.isRelative(path)) {
              final String convertedPath = globals.fs.path.join('..', '..', path);
              stringBuffer.writeln('  $name:');
              stringBuffer.writeln('    path: $convertedPath');
            } else {
              stringBuffer.writeln('  $name: $node');
            }
          } else {
            stringBuffer.writeln('  $name: $node');
          }
        }
      }
      stringBuffer.writeln('  build_runner: $kMinimumBuildRunnerVersion');
      stringBuffer.writeln('  build_daemon: $kSupportedBuildDaemonVersion');
      syntheticPubspec.writeAsStringSync(stringBuffer.toString());

      await pub.get(
        context: PubContext.pubGet,
        directory: generatedDirectory.path,
        upgrade: false,
        checkLastModified: false,
      );
      if (!scriptIdFile.existsSync()) {
        scriptIdFile.createSync(recursive: true);
      }
      scriptIdFile.writeAsBytesSync(appliedBuilderDigest);
      final ProcessResult generateResult = await globals.processManager.run(<String>[
        sdkBinaryName('pub'), 'run', 'build_runner', 'generate-build-script',
      ], workingDirectory: syntheticPubspec.parent.path);
      if (generateResult.exitCode != 0) {
        throwToolExit('Error generating build_script snapshot: ${generateResult.stderr}');
      }
      final File buildScript = globals.fs.file(generateResult.stdout.trim());
      final ProcessResult result = await globals.processManager.run(<String>[
        globals.artifacts.getArtifactPath(Artifact.engineDartBinary),
        '--snapshot=${buildSnapshot.path}',
        '--snapshot-kind=app-jit',
        '--packages=${globals.fs.path.join(generatedDirectory.path, '.packages')}',
        buildScript.path,
      ]);
      if (result.exitCode != 0) {
        throwToolExit('Error generating build_script snapshot: ${result.stderr}');
      }
    } finally {
      status.stop();
    }
  }

  @override
  Future<CodegenDaemon> daemon(
    FlutterProject flutterProject, {
    String mainPath,
    bool linkPlatformKernelIn = false,
    bool trackWidgetCreation = false,
    List<String> extraFrontEndOptions = const <String> [],
  }) async {
    await generateBuildScript(flutterProject);
    final String engineDartBinaryPath = globals.artifacts.getArtifactPath(Artifact.engineDartBinary);
    final File buildSnapshot = flutterProject
        .dartTool
        .childDirectory('build')
        .childDirectory('entrypoint')
        .childFile('build.dart.snapshot');
    final String scriptPackagesPath = flutterProject
        .dartTool
        .childDirectory('flutter_tool')
        .childFile('.packages')
        .path;
    final Status status = globals.logger.startProgress('starting build daemon...', timeout: null);
    BuildDaemonClient buildDaemonClient;
    try {
      final List<String> command = <String>[
        engineDartBinaryPath,
        '--packages=$scriptPackagesPath',
        buildSnapshot.path,
        'daemon',
        '--skip-build-script-check',
        '--delete-conflicting-outputs',
      ];
      buildDaemonClient = await BuildDaemonClient.connect(
        flutterProject.directory.path,
        command,
        logHandler: (ServerLog log) {
          if (log.message != null) {
            globals.printTrace(log.message);
          }
        },
      );
    } finally {
      status.stop();
    }
    // Empty string indicates we should build everything.
    final OutputLocation outputLocation = OutputLocation((OutputLocationBuilder b) => b
      ..output = ''
      ..useSymlinks = false
      ..hoist = false,
    );
    buildDaemonClient.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder builder) {
      builder.target = 'lib';
      builder.outputLocation = outputLocation.toBuilder();
    }));
    buildDaemonClient.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder builder) {
      builder.target = 'test';
      builder.outputLocation = outputLocation.toBuilder();
    }));
    return _BuildRunnerCodegenDaemon(buildDaemonClient);
  }
}

class _BuildRunnerCodegenDaemon implements CodegenDaemon {
  _BuildRunnerCodegenDaemon(this.buildDaemonClient);

  final BuildDaemonClient buildDaemonClient;

  @override
  CodegenStatus get lastStatus => _lastStatus;
  CodegenStatus _lastStatus;

  @override
  Stream<CodegenStatus> get buildResults => buildDaemonClient.buildResults.map((build.BuildResults results) {
    if (results.results.first.status == BuildStatus.failed) {
      return _lastStatus = CodegenStatus.Failed;
    }
    if (results.results.first.status == BuildStatus.started) {
      return _lastStatus = CodegenStatus.Started;
    }
    if (results.results.first.status == BuildStatus.succeeded) {
      return _lastStatus = CodegenStatus.Succeeded;
    }
    _lastStatus = null;
    return null;
  });

  @override
  void startBuild() {
    buildDaemonClient.startBuild();
  }
}

// Sorts the builders by name and produces a hashcode of the resulting iterable.
List<int> _produceScriptId(YamlMap builders) {
  if (builders == null || builders.isEmpty) {
    return md5.convert(globals.platform.version.codeUnits).bytes;
  }
  final List<String> orderedBuilderNames = builders.keys
    .cast<String>()
    .toList()..sort();
  final List<String> orderedBuilderValues = builders.values
    .map((dynamic value) => value.toString())
    .toList()..sort();
  return md5.convert(<String>[
    ...orderedBuilderNames,
    ...orderedBuilderValues,
    globals.platform.version,
  ].join('').codeUnits).bytes;
}
