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

const String angularDartProjectDirectory = '../app';
const String flutterProjectDirectory = '../app_flutter';

const String gcloudProjectIdFlag = 'project';
const String gcloudProjectIdAbbrFlag = 'p';

const String gcloudProjectVersionFlag = 'version';
const String gcloudProjectVersionAbbrFlag = 'v';

const String flutterProfileModeFlag = 'profile';
const String ignoreVersionFlag = 'ignore-version-check';
const String helpFlag = 'help';

String _gcloudProjectId;
String _gcloudProjectVersion;

bool _flutterProfileMode;
bool _ignoreVersion;

/// Check if [gcloudProjectIdFlag] and [gcloudProjectVersionFlag]
/// were passed as arguments. If they were, also set [_gcloudProjectId]
/// and [_gcloudProjectVersion] accordingly.
bool _getArgs(ArgParser argParser, List<String> arguments) {
  final ArgResults args = argParser.parse(arguments);

  final bool printHelpMessage = args[helpFlag] as bool;
  if (printHelpMessage) {
    return false;
  }

  _gcloudProjectId = args[gcloudProjectIdFlag] as String;
  _gcloudProjectVersion = args[gcloudProjectVersionFlag] as String;
  _flutterProfileMode = args[flutterProfileModeFlag] as bool;
  _ignoreVersion = args[ignoreVersionFlag] as bool;

  if (_gcloudProjectId == null) {
    stderr.write('--$gcloudProjectIdFlag must be defined\n');
    return false;
  }

  if (_gcloudProjectVersion == null) {
    stderr.write('--$gcloudProjectVersionFlag must be defined\n');
    return false;
  }

  return true;
}

/// Check the Flutter version installed and make sure it is a recent version
/// from the past 21 days.
///
/// Flutter tools handles the rest of the checks (e.g. Dart version) when
/// building the project.
Future<bool> _checkDependencies() async {
  if (_ignoreVersion) {
    return true;
  }

  stdout.writeln('Checking Flutter version via flutter --version');
  final ProcessResult result =
      await Process.run('flutter', <String>['--version']);
  final String flutterVersionOutput = result.stdout as String;

  // This makes an assumption that only the framework will have its version
  // printed out with the date in YYYY-MM-DD format.
  final RegExp dateRegExp =
      RegExp(r'([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))');
  final String flutterVersionDateRaw =
      dateRegExp.allMatches(flutterVersionOutput).first.group(0);

  final DateTime flutterVersionDate = DateTime.parse(flutterVersionDateRaw);
  final DateTime now = DateTime.now();
  final Duration lastUpdateToFlutter = now.difference(flutterVersionDate);

  return lastUpdateToFlutter.inDays < 21;
}

/// Build app Angular Dart project
Future<bool> _buildAngularDartApp() async {
  /// Clean up previous build files to ensure this codebase is deployed.
  await Process.run(
    'rm',
    <String>['-rf', 'build/'],
    workingDirectory: angularDartProjectDirectory,
  );

  final Process pubProcess = await Process.start('pub', <String>['get'],
      workingDirectory: angularDartProjectDirectory);
  await stdout.addStream(pubProcess.stdout);
  await stderr.addStream(pubProcess.stderr);
  if (await pubProcess.exitCode != 0) {
    return false;
  }

  final Process buildProcess = await Process.start(
    'pub',
    <String>[
      'run',
      'build_runner',
      'build',
      '--release',
      '--output',
      'build',
      '--delete-conflicting-outputs'
    ],
    workingDirectory: angularDartProjectDirectory,
  );
  await stdout.addStream(buildProcess.stdout);
  await stderr.addStream(buildProcess.stderr);

  // The Angular Dart build dashboard page has been replaced with a Flutter
  // version. There are some administrative features missing in the Flutter
  // version so we still offer the old build dashboard.
  await Process.run(
      'mv', <String>['build/web/build.html', 'build/web/old_build.html'],
      workingDirectory: angularDartProjectDirectory);

  return await buildProcess.exitCode == 0;
}

/// Build app_flutter for web.
Future<bool> _buildFlutterWebApp() async {
  /// Clean up previous build files to ensure this codebase is deployed.
  await Process.run('rm', <String>['-rf', 'build/'],
      workingDirectory: flutterProjectDirectory);

  final Process process = await Process.start(
      'flutter',
      <String>[
        'build',
        'web',
        '--dart-define',
        'FLUTTER_WEB_USE_SKIA=true',
        _flutterProfileMode ? '--profile' : '--release'
      ],
      workingDirectory: flutterProjectDirectory);
  await stdout.addStream(process.stdout);

  final bool successfulReturn = await process.exitCode == 0;

  return successfulReturn;
}

/// Copy the built project from app to this app_dart project.
Future<bool> _copyAngularDartProject() async {
  final ProcessResult result = await Process.run('cp',
      <String>['-rn', '$angularDartProjectDirectory/build/web', 'build/']);

  // On MacOS, this will return exit code 1 since this copy does
  // have files that "fail" to overwrite due to `app_flutter`.
  return result.exitCode == 0 || result.exitCode == 1;
}

/// Copy the built project from app_flutter to this app_dart project.
Future<bool> _copyFlutterApp() async {
  final ProcessResult result = await Process.run(
      'cp', <String>['-r', '$flutterProjectDirectory/build', 'build/']);

  return result.exitCode == 0;
}

/// Run the Google Cloud CLI tool to deploy to [_gcloudProjectId] under
/// version [_gcloudProjectVersion].
Future<bool> _deployToAppEngine() async {
  stdout.writeln('Deploying to AppEngine');

  /// The Google Cloud deployment command is an interactive process. It will
  /// print out what it is about to do, and ask for confirmation (Y/n).
  final Process process = await Process.start(
    'gcloud',
    <String>[
      'app',
      'deploy',
      '--project',
      _gcloudProjectId,
      '--version',
      _gcloudProjectVersion,
      '--no-promote',
      '--no-stop-previous-version',
    ],
  );

  /// Let this user confirm the details before Google Cloud sends for deployment.
  unawaited(stdin.pipe(process.stdin));

  await process.stderr.pipe(stderr);
  await process.stdout.pipe(stdout);

  return await process.exitCode == 0;
}

Future<void> main(List<String> arguments) async {
  final ArgParser argParser = ArgParser()
    ..addOption(gcloudProjectIdFlag, abbr: gcloudProjectIdAbbrFlag)
    ..addOption(gcloudProjectVersionFlag, abbr: gcloudProjectVersionAbbrFlag)
    ..addFlag(flutterProfileModeFlag)
    ..addFlag(ignoreVersionFlag)
    ..addFlag(helpFlag);

  if (!_getArgs(argParser, arguments)) {
    stdout.write('Required flags:\n'
        '--$gcloudProjectIdFlag gcp-id\n'
        '--$gcloudProjectVersionFlag version\n\n'
        'Optional flags:\n'
        '--$flutterProfileModeFlag\tBuild app_flutter in profile for debugging\n'
        '--$ignoreVersionFlag\tForce deploy with current Flutter version\n');
    exit(1);
  }

  if (!await _checkDependencies()) {
    stderr.writeln(
        'Update Flutter to a version on master from the past 3 weeks to deploy Cocoon');
    exit(1);
  }

  if (!await _buildAngularDartApp()) {
    stderr.writeln('Failed to build Angular Dart project');
    exit(1);
  }

  if (!await _buildFlutterWebApp()) {
    stderr.writeln('Failed to build Flutter app');
    exit(1);
  }

  /// Clean up previous build files to ensure the latest files are deployed.
  await Process.run('rm', <String>['-rf', 'build/']);

  if (!await _copyFlutterApp()) {
    stderr.writeln('Failed to copy Flutter app over');
    exit(1);
  }

  if (!await _copyAngularDartProject()) {
    stderr.writeln('Failed to copy Angular Dart project over');
    exit(1);
  }

  if (!await _deployToAppEngine()) {
    stderr.writeln('Failed to deploy to AppEngine');
    exit(1);
  }
}
