// Copyright 2019 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:io';

import 'package:args/args.dart';
import 'package:codesign/codesign.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:logging/logging.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';

/// Definitions of variables are included in help texts below.
const String kHelpFlag = 'help';
const String kDryrunFlag = 'dryrun';
const String kCodesignCertNameOption = 'codesign-cert-name';
const String kInputZipPathOption = 'input-zip-file-path';
const String kOutputZipPathOption = 'output-zip-file-path';
const String kAppSpecificPasswordOption = 'app-specific-password-file-path';
const String kCodesignAppstoreIDOption = 'codesign-appstore-id-file-path';
const String kCodesignTeamIDOption = 'codesign-team-id-file-path';

/// Perform Mac code signing based on file paths.
///
/// By default, if a user does not specify a dryrun flag, or selects dryrun
/// mode by providing the `--dryrun` flag, then [kDryrunFlag] is set to true,
/// a quick sanity check is performed and the notarization process is skipped.
/// On the other hand, if a user provides the flag `--no-dryrun`, [kDryrunFlag]
/// will be set to false, and code signed artifacts will go through the notarization
/// process.
///
/// For [kInputZipPathOption] and [kOutputZipPathOption], they are required parameter to specify the
/// input and output locations.
/// The codesign app will take the zip file located at the input location [kInputZipPathOption], and
/// put codesigned zip at [kOutputZipPathOption]. The work of downloading and uploading the zip
/// artifacts is delegated to recipe.
/// For example, supply
/// '--input-zip-file-path=/tmp/input.zip',
/// and code sign app will code sign the artifacts located at /tmp/input.zip.
///
/// For [kAppSpecificPasswordOption], [kCodesignAppstoreIDOption] and [kCodesignTeamIDOption],
/// they are file paths of the password files in the file system.
/// Each of the file paths stores a single line of sensitive password.
/// sensitive passwords include <CODESIGN_APPSTORE_ID>, <CODESIGN_TEAM_ID>, and <APP_SPECIFIC_PASSWORD>.
/// For example, if a user supplies --app-specific-password-file-path=/tmp/passwords.txt,
/// then we would be expecting a password file located at /tmp/passwords.txt.
/// The password file should contain the password name APP-SPECIFIC-PASSWORD and its value, deliminated by a single colon.
/// The content of a password file would look similar to:
/// APP-SPECIFIC-PASSWORD:789
///
/// [kCodesignCertNameOption] is public information. For codesigning flutter artifacts,
/// a user can provide values for this variable as shown in the example below.
///
/// Usage:
/// ```shell
/// dart run bin/codesign.dart --[no-]dryrun
/// --codesign-cert-name="FLUTTER.IO LLC"
/// --codesign-team-id-file-path=/a/b/c.txt
/// --codesign-appstore-id-file-path=/a/b/b.txt
/// --app-specific-password-file-path=/a/b/a.txt
/// --input-zip-file-path=/a/input.zip
/// --output-zip-file-path=/b/output.zip
/// ```
Future<void> main(List<String> args) async {
  Logger.root.onRecord.listen((LogRecord record) {
    stdout.writeln(record.toString());
  });

  final ArgParser parser = ArgParser();
  parser
    ..addFlag(
      kHelpFlag,
      help: 'Prints usage info.',
      callback: (bool value) {
        if (value) {
          stdout.write('${parser.usage}\n');
          exit(1);
        }
      },
    )
    ..addOption(
      kCodesignCertNameOption,
      help: 'The name of the codesign certificate to be used when codesigning.'
          'the name of the certificate for flutter, for example, is: FLUTTER.IO LLC',
    )
    ..addOption(
      kInputZipPathOption,
      help: 'File path to the unsigned artifact zip file.',
    )
    ..addOption(
      kOutputZipPathOption,
      help: 'File path to codesigned artifact zip file for output.',
    )
    ..addOption(
      kAppSpecificPasswordOption,
      help:
          'The file path of a password file in file system. The password file stores the sensitive password <APP-SPECIFIC-PASSWORD>.',
    )
    ..addOption(
      kCodesignAppstoreIDOption,
      help:
          'The file path of a password file in file system. The password file stores the sensitive password <CODESIGN_APPSTORE_ID>.',
    )
    ..addOption(
      kCodesignTeamIDOption,
      help:
          'The file path of a password file in file system. The password file stores the sensitive password <CODESIGN_TEAM_ID>.',
    )
    ..addFlag(
      kDryrunFlag,
      defaultsTo: true,
      help: 'whether we are going to skip the notarization process.',
    );

  final ArgResults argResults = parser.parse(args);

  const Platform platform = LocalPlatform();

  final String codesignCertName = getValueFromArgs(kCodesignCertNameOption, argResults)!;
  final String inputZipPath = getValueFromArgs(kInputZipPathOption, argResults)!;
  final String outputZipPath = getValueFromArgs(kOutputZipPathOption, argResults)!;
  final String appSpecificPasswordFilePath = getValueFromArgs(kAppSpecificPasswordOption, argResults)!;
  final String codesignAppstoreIDFilePath = getValueFromArgs(kCodesignAppstoreIDOption, argResults)!;
  final String codesignTeamIDFilePath = getValueFromArgs(kCodesignTeamIDOption, argResults)!;

  final bool dryrun = argResults[kDryrunFlag] as bool;

  if (!platform.isMacOS) {
    throw CodesignException(
      'Error! Expected operating system "macos", actual operating system is: '
      '"${platform.operatingSystem}"',
    );
  }

  const FileSystem fileSystem = LocalFileSystem();
  final Directory rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
  const ProcessManager processManager = LocalProcessManager();

  return FileCodesignVisitor(
    codesignCertName: codesignCertName,
    fileSystem: fileSystem,
    rootDirectory: rootDirectory,
    appSpecificPasswordFilePath: appSpecificPasswordFilePath,
    codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
    codesignTeamIDFilePath: codesignTeamIDFilePath,
    processManager: processManager,
    dryrun: dryrun,
    inputZipPath: inputZipPath,
    outputZipPath: outputZipPath,
  ).validateAll();
}
