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

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,
    );
  }

  @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: boolArgDeprecated('all'),
          verbose: globalResults?['verbose'] == 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;
    final String currentBranch = globals.flutterVersion.getBranchName();
    final Set<String> seenUnofficialChannels = <String>{};
    final List<String> rawOutput = <String>[];

    showAll = showAll || currentChannel != currentBranch;

    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 List<String> officialChannels = kOfficialChannels.toList();
    final List<bool> availableChannels = List<bool>.filled(officialChannels.length, false);

    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 (split.length > 1) {
        final int index = officialChannels.indexOf(branch);

        if (index != -1) { // Mark all available channels official channels from output
          availableChannels[index] = true;
        } else if (showAll && !seenUnofficialChannels.contains(branch)) {
        // add other branches to seenUnofficialChannels if --all flag is given (to print later)
          seenUnofficialChannels.add(branch);
        }
      }
    }

    // print all available official channels in sorted manner
    for (int i = 0; i < officialChannels.length; i++) {
      // only print non-missing channels
      if (availableChannels[i]) {
        String currentIndicator = ' ';
        if (officialChannels[i] == currentChannel) {
          currentIndicator = '*';
        }
        globals.printStatus('$currentIndicator ${officialChannels[i]}');
      }
    }

    // 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');
        }
      }
    }

    if (currentChannel == 'unknown') {
      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);
    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.
    int result = await globals.processUtils.stream(
      <String>['git', 'fetch'],
      workingDirectory: Cache.flutterRoot,
      prefix: 'git: ',
    );

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