// 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 '../base/common.dart';
import '../base/process.dart';
import '../cache.dart';
import '../globals.dart' as globals;
import '../runner/flutter_command.dart';
import '../runner/flutter_command_runner.dart';
import '../version.dart';

import 'upgrade.dart' show precacheArtifacts;

class ChannelCommand extends FlutterCommand {
  ChannelCommand({ bool verboseHelp = false }) {
    argParser.addFlag(
      'all',
      abbr: 'a',
      help: 'Include all the available branches (including local branches) when listing channels.',
      hide: !verboseHelp,
    );
    argParser.addFlag(
      'cache-artifacts',
      help: 'After switching channels, download all required binary artifacts. '
            'This is the equivalent of running "flutter precache" with the "--all-platforms" flag.',
      defaultsTo: true,
    );
  }

  @override
  final String name = 'channel';

  @override
  final String description = 'List or switch Flutter channels.';

  @override
  final String category = FlutterCommandCategory.sdk;

  @override
  String get invocation => '${runner?.executableName} $name [<channel-name>]';

  @override
  Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{};

  @override
  Future<FlutterCommandResult> runCommand() async {
    final List<String> rest = argResults?.rest ?? <String>[];
    switch (rest.length) {
      case 0:
        await _listChannels(
          showAll: boolArg('all'),
          verbose: globalResults?[FlutterGlobalOptions.kVerboseFlag] == true,
        );
        return FlutterCommandResult.success();
      case 1:
        await _switchChannel(rest[0]);
        return FlutterCommandResult.success();
      default:
        throw ToolExit('Too many arguments.\n$usage');
    }
  }

  Future<void> _listChannels({ required bool showAll, required bool verbose }) async {
    // Beware: currentBranch could contain PII. See getBranchName().
    final String currentChannel = globals.flutterVersion.channel; // limited to known branch names
    assert(kOfficialChannels.contains(currentChannel) || kObsoleteBranches.containsKey(currentChannel) || currentChannel == kUserBranch, 'potential PII leak in channel name: "$currentChannel"');
    final String currentBranch = globals.flutterVersion.getBranchName();
    final Set<String> seenUnofficialChannels = <String>{};
    final List<String> rawOutput = <String>[];

    globals.printStatus('Flutter channels:');
    final int result = await globals.processUtils.stream(
      <String>['git', 'branch', '-r'],
      workingDirectory: Cache.flutterRoot,
      mapFunction: (String line) {
        rawOutput.add(line);
        return null;
      },
    );
    if (result != 0) {
      final String details = verbose ? '\n${rawOutput.join('\n')}' : '';
      throwToolExit('List channels failed: $result$details', exitCode: result);
    }

    final Set<String> availableChannels = <String>{};

    for (final String line in rawOutput) {
      final List<String> split = line.split('/');
      if (split.length != 2) {
        // We don't know how to parse this line, skip it.
        continue;
      }
      final String branch = split[1];
      if (kOfficialChannels.contains(branch)) {
        availableChannels.add(branch);
      } else if (showAll) {
        seenUnofficialChannels.add(branch);
      }
    }

    bool currentChannelIsOfficial = false;

    // print all available official channels in sorted manner
    for (final String channel in kOfficialChannels) {
      // only print non-missing channels
      if (availableChannels.contains(channel)) {
        String currentIndicator = ' ';
        if (channel == currentChannel) {
          currentIndicator = '*';
          currentChannelIsOfficial = true;
        }
        globals.printStatus('$currentIndicator $channel (${kChannelDescriptions[channel]})');
      }
    }

    // print all remaining channels if showAll is true
    if (showAll) {
      for (final String branch in seenUnofficialChannels) {
        if (currentBranch == branch) {
          globals.printStatus('* $branch');
        } else if (!branch.startsWith('HEAD ')) {
          globals.printStatus('  $branch');
        }
      }
    } else if (!currentChannelIsOfficial) {
      globals.printStatus('* $currentBranch');
    }

    if (!currentChannelIsOfficial) {
      assert(currentChannel == kUserBranch, 'Current channel is "$currentChannel", which is not an official branch. (Current branch is "$currentBranch".)');
      globals.printStatus('');
      globals.printStatus('Currently not on an official channel.');
    }
  }

  Future<void> _switchChannel(String branchName) async {
    globals.printStatus("Switching to flutter channel '$branchName'...");
    if (kObsoleteBranches.containsKey(branchName)) {
      final String alternative = kObsoleteBranches[branchName]!;
      globals.printStatus("This channel is obsolete. Consider switching to the '$alternative' channel instead.");
    } else if (!kOfficialChannels.contains(branchName)) {
      globals.printStatus('This is not an official channel. For a list of available channels, try "flutter channel".');
    }
    await _checkout(branchName);
    if (boolArg('cache-artifacts')) {
      await precacheArtifacts(Cache.flutterRoot);
    }
    globals.printStatus("Successfully switched to flutter channel '$branchName'.");
    globals.printStatus("To ensure that you're on the latest build from this channel, run 'flutter upgrade'");
  }

  static Future<void> upgradeChannel(FlutterVersion currentVersion) async {
    final String channel = currentVersion.channel;
    if (kObsoleteBranches.containsKey(channel)) {
      final String alternative = kObsoleteBranches[channel]!;
      globals.printStatus("Transitioning from '$channel' to '$alternative'...");
      return _checkout(alternative);
    }
  }

  static Future<void> _checkout(String branchName) async {
    // Get latest refs from upstream.
    RunResult runResult = await globals.processUtils.run(
      <String>['git', 'fetch'],
      workingDirectory: Cache.flutterRoot,
    );

    if (runResult.processResult.exitCode == 0) {
      runResult = await globals.processUtils.run(
        <String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/$branchName'],
        workingDirectory: Cache.flutterRoot,
      );
      if (runResult.processResult.exitCode == 0) {
        // branch already exists, try just switching to it
        runResult = await globals.processUtils.run(
          <String>['git', 'checkout', branchName, '--'],
          workingDirectory: Cache.flutterRoot,
        );
      } else {
        // branch does not exist, we have to create it
        runResult = await globals.processUtils.run(
          <String>['git', 'checkout', '--track', '-b', branchName, 'origin/$branchName'],
          workingDirectory: Cache.flutterRoot,
        );
      }
    }
    if (runResult.processResult.exitCode != 0) {
      throwToolExit(
        'Switching channels failed\n$runResult.',
        exitCode: runResult.processResult.exitCode,
      );
    } else {
      // Remove the version check stamp, since it could contain out-of-date
      // information that pertains to the previous channel.
      await FlutterVersion.resetFlutterVersionFreshnessCheck();
    }
  }
}
