// 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:pool/pool.dart';

import '../../asset.dart';
import '../../base/file_system.dart';
import '../../base/logger.dart';
import '../../build_info.dart';
import '../../convert.dart';
import '../../devfs.dart';
import '../build_system.dart';
import '../depfile.dart';
import 'common.dart';
import 'icon_tree_shaker.dart';
import 'shader_compiler.dart';

/// A helper function to copy an asset bundle into an [environment]'s output
/// directory.
///
/// Throws [Exception] if [AssetBundle.build] returns a non-zero exit code.
///
/// [additionalContent] may contain additional DevFS entries that will be
/// included in the final bundle, but not the AssetManifest.json file.
///
/// Returns a [Depfile] containing all assets used in the build.
Future<Depfile> copyAssets(
  Environment environment,
  Directory outputDirectory, {
  Map<String, DevFSContent>? additionalContent,
  required TargetPlatform targetPlatform,
  BuildMode? buildMode,
}) async {
  // Check for an SkSL bundle.
  final String? shaderBundlePath = environment.defines[kBundleSkSLPath] ?? environment.inputs[kBundleSkSLPath];
  final DevFSContent? skslBundle = processSkSLBundle(
    shaderBundlePath,
    engineVersion: environment.engineVersion,
    fileSystem: environment.fileSystem,
    logger: environment.logger,
    targetPlatform: targetPlatform,
  );

  final File pubspecFile =  environment.projectDir.childFile('pubspec.yaml');
  // Only the default asset bundle style is supported in assemble.
  final AssetBundle assetBundle = AssetBundleFactory.defaultInstance(
    logger: environment.logger,
    fileSystem: environment.fileSystem,
    platform: environment.platform,
    splitDeferredAssets: buildMode != BuildMode.debug && buildMode != BuildMode.jitRelease,
  ).createBundle();
  final int resultCode = await assetBundle.build(
    manifestPath: pubspecFile.path,
    packagesPath: environment.projectDir.childFile('.packages').path,
    deferredComponentsEnabled: environment.defines[kDeferredComponents] == 'true',
    targetPlatform: targetPlatform,
  );
  if (resultCode != 0) {
    throw Exception('Failed to bundle asset files.');
  }
  final Pool pool = Pool(kMaxOpenFiles);
  final List<File> inputs = <File>[
    // An asset manifest with no assets would have zero inputs if not
    // for this pubspec file.
    pubspecFile,
  ];
  final List<File> outputs = <File>[];

  final IconTreeShaker iconTreeShaker = IconTreeShaker(
    environment,
    assetBundle.entries[kFontManifestJson] as DevFSStringContent?,
    processManager: environment.processManager,
    logger: environment.logger,
    fileSystem: environment.fileSystem,
    artifacts: environment.artifacts,
  );
  final ShaderCompiler shaderCompiler = ShaderCompiler(
    processManager: environment.processManager,
    logger: environment.logger,
    fileSystem: environment.fileSystem,
    artifacts: environment.artifacts,
  );

  final Map<String, DevFSContent> assetEntries = <String, DevFSContent>{
    ...assetBundle.entries,
    ...?additionalContent,
    if (skslBundle != null)
      kSkSLShaderBundlePath: skslBundle,
  };
  final Map<String, AssetKind> entryKinds = <String, AssetKind>{
    ...assetBundle.entryKinds,
  };

  await Future.wait<void>(
    assetEntries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
      final PoolResource resource = await pool.request();
      try {
        // This will result in strange looking files, for example files with `/`
        // on Windows or files that end up getting URI encoded such as `#.ext`
        // to `%23.ext`. However, we have to keep it this way since the
        // platform channels in the framework will URI encode these values,
        // and the native APIs will look for files this way.
        final File file = environment.fileSystem.file(
          environment.fileSystem.path.join(outputDirectory.path, entry.key));
        final AssetKind assetKind = entryKinds[entry.key] ?? AssetKind.regular;
        outputs.add(file);
        file.parent.createSync(recursive: true);
        final DevFSContent content = entry.value;
        if (content is DevFSFileContent && content.file is File) {
          inputs.add(content.file as File);
          bool doCopy = true;
          switch (assetKind) {
            case AssetKind.regular:
              break;
            case AssetKind.font:
              doCopy = !await iconTreeShaker.subsetFont(
                input: content.file as File,
                outputPath: file.path,
                relativePath: entry.key,
              );
              break;
            case AssetKind.shader:
              doCopy = !await shaderCompiler.compileShader(
                input: content.file as File,
                outputPath: file.path,
              );
              break;
          }
          if (doCopy) {
            await (content.file as File).copy(file.path);
          }
        } else {
          await file.writeAsBytes(await entry.value.contentsAsBytes());
        }
      } finally {
        resource.release();
      }
  }));

  // Copy deferred components assets only for release or profile builds.
  // The assets are included in assetBundle.entries as a normal asset when
  // building as debug.
  if (environment.defines[kDeferredComponents] == 'true' && buildMode != null) {
    await Future.wait<void>(assetBundle.deferredComponentsEntries.entries.map<Future<void>>(
      (MapEntry<String, Map<String, DevFSContent>> componentEntries) async {
        final Directory componentOutputDir =
            environment.projectDir
                .childDirectory('build')
                .childDirectory(componentEntries.key)
                .childDirectory('intermediates')
                .childDirectory('flutter');
        await Future.wait<void>(
          componentEntries.value.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
            final PoolResource resource = await pool.request();
            try {
              // This will result in strange looking files, for example files with `/`
              // on Windows or files that end up getting URI encoded such as `#.ext`
              // to `%23.ext`. However, we have to keep it this way since the
              // platform channels in the framework will URI encode these values,
              // and the native APIs will look for files this way.

              // If deferred components are disabled, then copy assets to regular location.
              final File file = environment.defines[kDeferredComponents] == 'true'
                ? environment.fileSystem.file(
                    environment.fileSystem.path.join(componentOutputDir.path, buildMode.name, 'deferred_assets', 'flutter_assets', entry.key))
                : environment.fileSystem.file(
                    environment.fileSystem.path.join(outputDirectory.path, entry.key));
              outputs.add(file);
              file.parent.createSync(recursive: true);
              final DevFSContent content = entry.value;
              if (content is DevFSFileContent && content.file is File) {
                inputs.add(content.file as File);
                if (!await iconTreeShaker.subsetFont(
                  input: content.file as File,
                  outputPath: file.path,
                  relativePath: entry.key,
                )) {
                  await (content.file as File).copy(file.path);
                }
              } else {
                await file.writeAsBytes(await entry.value.contentsAsBytes());
              }
            } finally {
              resource.release();
            }
        }));
    }));
  }
  final Depfile depfile = Depfile(inputs + assetBundle.additionalDependencies, outputs);
  if (shaderBundlePath != null) {
    final File skSLBundleFile = environment.fileSystem
      .file(shaderBundlePath).absolute;
    depfile.inputs.add(skSLBundleFile);
  }
  return depfile;
}

/// The path of the SkSL JSON bundle included in flutter_assets.
const String kSkSLShaderBundlePath = 'io.flutter.shaders.json';

/// Validate and process an SkSL asset bundle in a [DevFSContent].
///
/// Returns `null` if the bundle was not provided, otherwise attempts to
/// validate the bundle.
///
/// Throws [Exception] if the bundle is invalid due to formatting issues.
///
/// If the current target platform is different than the platform constructed
/// for the bundle, a warning will be printed.
DevFSContent? processSkSLBundle(String? bundlePath, {
  required TargetPlatform targetPlatform,
  required FileSystem fileSystem,
  required Logger logger,
  String? engineVersion,
}) {
  if (bundlePath == null) {
    return null;
  }
  // Step 1: check that file exists.
  final File skSLBundleFile = fileSystem.file(bundlePath);
  if (!skSLBundleFile.existsSync()) {
    logger.printError('$bundlePath does not exist.');
    throw Exception('SkSL bundle was invalid.');
  }

  // Step 2: validate top level bundle structure.
  Map<String, Object?>? bundle;
  try {
    final Object? rawBundle = json.decode(skSLBundleFile.readAsStringSync());
    if (rawBundle is Map<String, Object?>) {
      bundle = rawBundle;
    } else {
      logger.printError('"$bundle" was not a JSON object: $rawBundle');
      throw Exception('SkSL bundle was invalid.');
    }
  } on FormatException catch (err) {
    logger.printError('"$bundle" was not a JSON object: $err');
    throw Exception('SkSL bundle was invalid.');
  }
  // Step 3: Validate that:
  // * The engine revision the bundle was compiled with
  //   is the same as the current revision.
  // * The target platform is the same (this one is a warning only).
  final String? bundleEngineRevision = bundle['engineRevision'] as String?;
  if (bundleEngineRevision != engineVersion) {
    logger.printError(
      'Expected Flutter $bundleEngineRevision, but found $engineVersion\n'
      'The SkSL bundle was produced with a different engine version. It must '
      'be recreated for the current Flutter version.'
    );
    throw Exception('SkSL bundle was invalid');
  }

  final String? parsedPlatform = bundle['platform'] as String?;
  TargetPlatform? bundleTargetPlatform;
  if (parsedPlatform != null) {
    bundleTargetPlatform = getTargetPlatformForName(parsedPlatform);
  }
  if (bundleTargetPlatform == null || bundleTargetPlatform != targetPlatform) {
    logger.printError(
      'The SkSL bundle was created for $bundleTargetPlatform, but the current '
      'platform is $targetPlatform. This may lead to less efficient shader '
      'caching.'
    );
  }
  return DevFSStringContent(json.encode(<String, Object?>{
    'data': bundle['data'],
  }));
}

/// Copy the assets defined in the flutter manifest into a build directory.
class CopyAssets extends Target {
  const CopyAssets();

  @override
  String get name => 'copy_assets';

  @override
  List<Target> get dependencies => const <Target>[
    KernelSnapshot(),
  ];

  @override
  List<Source> get inputs => const <Source>[
    Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/assets.dart'),
    ...IconTreeShaker.inputs,
    ...ShaderCompiler.inputs,
  ];

  @override
  List<Source> get outputs => const <Source>[];

  @override
  List<String> get depfiles => const <String>[
    'flutter_assets.d',
  ];

  @override
  Future<void> build(Environment environment) async {
    final Directory output = environment
      .buildDir
      .childDirectory('flutter_assets');
    output.createSync(recursive: true);
    final Depfile depfile = await copyAssets(
      environment,
      output,
      targetPlatform: TargetPlatform.android,
    );
    final DepfileService depfileService = DepfileService(
      fileSystem: environment.fileSystem,
      logger: environment.logger,
    );
    depfileService.writeToFile(
      depfile,
      environment.buildDir.childFile('flutter_assets.d'),
    );
  }
}
