// 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.

// Shared logic between iOS and macOS implementations of native assets.

import 'package:native_assets_cli/native_assets_cli_internal.dart';

import '../../../base/common.dart';
import '../../../base/file_system.dart';
import '../../../base/io.dart';
import '../../../build_info.dart';
import '../../../convert.dart';
import '../../../globals.dart' as globals;

/// Create an `Info.plist` in [target] for a framework with a single dylib.
///
/// The framework must be named [name].framework and the dylib [name].
Future<void> createInfoPlist(
  String name,
  Directory target, {
  String? minimumIOSVersion,
}) async {
  final File infoPlistFile = target.childFile('Info.plist');
  final String bundleIdentifier = 'io.flutter.flutter.native_assets.$name'.replaceAll('_', '-');
  await infoPlistFile.writeAsString(<String>[
    '''
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$name</string>
	<key>CFBundleIdentifier</key>
	<string>$bundleIdentifier</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$name</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1.0</string>
''',
    if (minimumIOSVersion != null)
      '''
	<key>MinimumOSVersion</key>
	<string>$minimumIOSVersion</string>
''',
    '''
</dict>
</plist>'''
  ].join());
}

/// Combines dylibs from [sources] into a fat binary at [targetFullPath].
///
/// The dylibs must have different architectures. E.g. a dylib targeting
/// arm64 ios simulator cannot be combined with a dylib targeting arm64
/// ios device or macos arm64.
Future<void> lipoDylibs(File target, List<Uri> sources) async {
  final ProcessResult lipoResult = await globals.processManager.run(
    <String>[
      'lipo',
      '-create',
      '-output',
      target.path,
      for (final Uri source in sources) source.toFilePath(),
    ],
  );
  if (lipoResult.exitCode != 0) {
    throwToolExit('Failed to create universal binary:\n${lipoResult.stderr}');
  }
  globals.logger.printTrace(lipoResult.stdout as String);
  globals.logger.printTrace(lipoResult.stderr as String);
}

/// Sets the install name in a dylib with a Mach-O format.
///
/// On macOS and iOS, opening a dylib at runtime fails if the path inside the
/// dylib itself does not correspond to the path that the file is at. Therefore,
/// native assets copied into their final location also need their install name
/// updated with the `install_name_tool`.
Future<void> setInstallNameDylib(File dylibFile) async {
  final String fileName = dylibFile.basename;
  final ProcessResult installNameResult = await globals.processManager.run(
    <String>[
      'install_name_tool',
      '-id',
      '@rpath/$fileName.framework/$fileName',
      dylibFile.path,
    ],
  );
  if (installNameResult.exitCode != 0) {
    throwToolExit(
      'Failed to change the install name of $dylibFile:\n${installNameResult.stderr}',
    );
  }
}

Future<void> codesignDylib(
  String? codesignIdentity,
  BuildMode buildMode,
  FileSystemEntity target,
) async {
  if (codesignIdentity == null || codesignIdentity.isEmpty) {
    codesignIdentity = '-';
  }
  final List<String> codesignCommand = <String>[
    'codesign',
    '--force',
    '--sign',
    codesignIdentity,
    if (buildMode != BuildMode.release) ...<String>[
      // Mimic Xcode's timestamp codesigning behavior on non-release binaries.
      '--timestamp=none',
    ],
    target.path,
  ];
  globals.logger.printTrace(codesignCommand.join(' '));
  final ProcessResult codesignResult = await globals.processManager.run(
    codesignCommand,
  );
  if (codesignResult.exitCode != 0) {
    throwToolExit(
      'Failed to code sign binary: exit code: ${codesignResult.exitCode} '
      '${codesignResult.stdout} ${codesignResult.stderr}',
    );
  }
  globals.logger.printTrace(codesignResult.stdout as String);
  globals.logger.printTrace(codesignResult.stderr as String);
}

/// Flutter expects `xcrun` to be on the path on macOS hosts.
///
/// Use the `clang`, `ar`, and `ld` that would be used if run with `xcrun`.
Future<CCompilerConfigImpl> cCompilerConfigMacOS() async {
  final ProcessResult xcrunResult = await globals.processManager.run(
    <String>['xcrun', 'clang', '--version'],
  );
  if (xcrunResult.exitCode != 0) {
    throwToolExit('Failed to find clang with xcrun:\n${xcrunResult.stderr}');
  }
  final String installPath = LineSplitter.split(xcrunResult.stdout as String)
      .firstWhere((String s) => s.startsWith('InstalledDir: '))
      .split(' ')
      .last;
  return CCompilerConfigImpl(
    compiler: Uri.file('$installPath/clang'),
    archiver: Uri.file('$installPath/ar'),
    linker: Uri.file('$installPath/ld'),
  );
}

/// Converts [fileName] into a suitable framework name.
///
/// On MacOS and iOS, dylibs need to be packaged in a framework.
///
/// In order for resolution to work, the file name inside the framework must be
/// equal to the framework name.
///
/// Dylib names on MacOS/iOS usually have a dylib extension. If so, remove it.
///
/// Dylib names on MacOS/iOS are usually prefixed with 'lib'. So, if the file is
/// a dylib, try to remove the prefix.
///
/// The bundle ID string must contain only alphanumeric characters
/// (A–Z, a–z, and 0–9), hyphens (-), and periods (.).
/// https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleidentifier
///
/// The [alreadyTakenNames] are used to ensure that the framework name does not
/// conflict with previously chosen names.
Uri frameworkUri(String fileName, Set<String> alreadyTakenNames) {
  final List<String> splitFileName = fileName.split('.');
  final bool isDylib;
  if (splitFileName.length >= 2) {
    isDylib = splitFileName.last == 'dylib';
    if (isDylib) {
      fileName = splitFileName.sublist(0, splitFileName.length - 1).join('.');
    }
  } else {
    isDylib = false;
  }
  if (isDylib && fileName.startsWith('lib')) {
    fileName = fileName.replaceFirst('lib', '');
  }
  fileName = fileName.replaceAll(RegExp(r'[^A-Za-z0-9_-]'), '');
  if (alreadyTakenNames.contains(fileName)) {
    final String prefixName = fileName;
    for (int i = 1; i < 1000; i++) {
      fileName = '$prefixName$i';
      if (!alreadyTakenNames.contains(fileName)) {
        break;
      }
    }
    if (alreadyTakenNames.contains(fileName)) {
      throwToolExit('Failed to rename $fileName in native assets packaging.');
    }
  }
  alreadyTakenNames.add(fileName);
  return Uri(path: '$fileName.framework/$fileName');
}
