import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:_discoveryapis_commons/_discoveryapis_commons.dart';
import 'package:googleapis/storage/v1.dart' as storage;
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as p;

const GITHUB_REPO = 'dart-lang/homebrew-dart';

const CHANNELS = const ['dev', 'stable'];

const FILES = const {
  'dev': const [x64File, ia32File],
  'stable': const [x64File, ia32File, dartiumFile, contentShellFile]
};

const urlBase = 'https://storage.googleapis.com/dart-archive/channels';
const x64File = 'sdk/dartsdk-macos-x64-release.zip';
const ia32File = 'sdk/dartsdk-macos-ia32-release.zip';
const dartiumFile = 'dartium/dartium-macos-x64-release.zip';
const contentShellFile = 'dartium/content_shell-macos-x64-release.zip';

const dartRbFileName = 'dart.rb';
const dart2RbFileName = 'dart@2.rb';

Future<String> getHash256(
    String channel, String revision, String download) async {
  var client = new http.Client();
  try {
    var api = new storage.StorageApi(client);
    var media = await api.objects.get('dart-archive',
        'channels/$channel/release/$revision/$download.sha256sum',
        downloadOptions: DownloadOptions.FullMedia);

    var hashLine = await ascii.decodeStream(media.stream);
    return new RegExp('[0-9a-fA-F]*').stringMatch(hashLine);
  } finally {
    client.close();
  }
}

Future<String> getVersion(String channel, String revision) async {
  var client = new http.Client();
  try {
    var api = new storage.StorageApi(client);

    var media = await api.objects.get(
        'dart-archive', 'channels/$channel/release/$revision/VERSION',
        downloadOptions: DownloadOptions.FullMedia);

    var versionObject = await json.fuse(ascii).decoder.bind(media.stream).first;
    return versionObject['version'];
  } finally {
    client.close();
  }
}

Future<Map> getCurrentRevisions(String repository) async {
  var revisions = <String, String>{};
  var lines =
      await (new File(p.join(repository, dartRbFileName))).readAsLines();

  for (var channel in CHANNELS) {
    /// This RegExp between release/ and /sdk matches
    /// * 1 digit followed by
    /// * Any number of letters, numbers, dashes and dots
    /// This covers both numeric- and version-formatted revisions
    ///
    /// Note: all of the regexp escape slashes `\` are double-escaped within the
    /// Dart string
    final regExp =
        new RegExp('channels/$channel/release/(\\d[\\w\\d\\-\\.]*)/sdk');

    revisions[channel] =
        regExp.firstMatch(lines.firstWhere(regExp.hasMatch)).group(1);
  }
  return revisions;
}

Future<Map> getHashes(Map revisions) async {
  var hashes = <String, Map>{};
  for (var channel in CHANNELS) {
    hashes[channel] = {};
    for (var file in FILES[channel]) {
      var hash = await getHash256(channel, revisions[channel], file);
      hashes[channel][file] = hash;
    }
  }
  return hashes;
}

Future writeHomebrewInfo(
    String channel, String revision, String repository) async {
  var revisions = await getCurrentRevisions(repository);

  if (revisions[channel] == revision) {
    print("Channel $channel is already at revision $revision in homebrew.");
    exit(0);
  }
  revisions[channel] = revision;
  var hashes = await getHashes(revisions);
  var devVersion = await getVersion('dev', revisions['dev']);

  var stableVersion = await getVersion('stable', revisions['stable']);

  await new File(p.join(repository, dartRbFileName)).writeAsString(
      createDartFormula(revisions, hashes, devVersion, stableVersion),
      flush: true);
  await new File(p.join(repository, dart2RbFileName)).writeAsString(
      createDart2Formula(revisions, hashes, devVersion, stableVersion),
      flush: true);
}

String createDartFormula(
        Map revisions, Map hashes, String devVersion, String stableVersion) =>
    '''
class Dart < Formula
  desc "The Dart SDK"
  homepage "https://www.dartlang.org/"

  version "$stableVersion"
  if MacOS.prefer_64_bit?
    url "$urlBase/stable/release/${revisions['stable']}/$x64File"
    sha256 "${hashes['stable'][x64File]}"
  else
    url "$urlBase/stable/release/${revisions['stable']}/$ia32File"
    sha256 "${hashes['stable'][ia32File]}"
  end

  devel do
    version "$devVersion"
    if MacOS.prefer_64_bit?
      url "$urlBase/dev/release/${revisions['dev']}/$x64File"
      sha256 "${hashes['dev'][x64File]}"
    else
      url "$urlBase/dev/release/${revisions['dev']}/$ia32File"
      sha256 "${hashes['dev'][ia32File]}"
    end
  end

  option "with-content-shell", "Download and install content_shell -- headless Dartium for testing"
  option "with-dartium", "Download and install Dartium -- Chromium with Dart"

  resource "content_shell" do
    version "$stableVersion"
    url "$urlBase/stable/release/${revisions['stable']}/$contentShellFile"
    sha256 "${hashes['stable'][contentShellFile]}"
  end

  resource "dartium" do
    version "$stableVersion"
    url "$urlBase/stable/release/${revisions['stable']}/$dartiumFile"
    sha256 "${hashes['stable'][dartiumFile]}"
  end

  def install
    libexec.install Dir["*"]
    bin.install_symlink "#{libexec}/bin/dart"
    bin.write_exec_script Dir["#{libexec}/bin/{pub,dart?*}"]

    if build.with? "dartium"
      if build.devel?
        odie "dartium is no longer supported with --devel builds. Remove --with-dartium and try again."
      end
      dartium_binary = "Chromium.app/Contents/MacOS/Chromium"
      prefix.install resource("dartium")
      (bin+"dartium").write shim_script dartium_binary
    end

    if build.with? "content-shell"
      if build.devel?
        odie "content-shell is no longer supported with --devel builds. Remove --with-content-shell and try again."
      end
      content_shell_binary = "Content Shell.app/Contents/MacOS/Content Shell"
      prefix.install resource("content_shell")
      (bin+"content_shell").write shim_script content_shell_binary
    end
  end

  def shim_script(target)
    <<~EOS
      #!/usr/bin/env bash
      exec "#{prefix}/#{target}" "\$@"
    EOS
  end

  def caveats; <<~EOS
    Please note the path to the Dart SDK:
      #{opt_libexec}
    EOS
  end

  test do
    (testpath/"sample.dart").write <<~EOS
      void main() {
        print(r"test message");
      }
    EOS

    assert_equal "test message\\n", shell_output("#{bin}/dart sample.dart")
  end
end
''';

/// TODO: Remove this formula after Dart 2 is released as stable.
/// This is a transitional mechanism to support developers migrating
/// from Dart 1 to Dart 2 while it's in pre-release.
String createDart2Formula(
        Map revisions, Map hashes, String devVersion, String stableVersion) =>
    '''
class DartAT2 < Formula
  desc "The Dart 2 SDK"
  homepage "https://www.dartlang.org/"
  version "$devVersion"

  keg_only :versioned_formula

  if MacOS.prefer_64_bit?
    url "$urlBase/dev/release/${revisions['dev']}/$x64File"
    sha256 "${hashes['dev'][x64File]}"
  else
    url "$urlBase/dev/release/${revisions['dev']}/$ia32File"
    sha256 "${hashes['dev'][ia32File]}"
  end

  def install
    libexec.install Dir["*"]
    bin.install_symlink "#{libexec}/bin/dart"
    bin.write_exec_script Dir["#{libexec}/bin/{pub,dart?*}"]
  end

  def shim_script(target)
    <<~EOS
      #!/usr/bin/env bash
      exec "#{prefix}/#{target}" "\$@"
    EOS
  end

  def caveats; <<~EOS
    Note that this is a prerelease version of Dart.

    Please note the path to the Dart SDK:
      #{opt_libexec}
    EOS
  end

  test do
    (testpath/"sample.dart").write <<~EOS
      void main() {
        print(r"test message");
      }
    EOS

    assert_equal "test message\n", shell_output("#{bin}/dart sample.dart")
  end
end
''';

Future runGit(List<String> args, String repository,
    Map<String, String> gitEnvironment) async {
  print("git ${args.join(' ')}");

  var result = await Process.run('git', args,
      workingDirectory: repository, environment: gitEnvironment);

  print(result.stdout);
  print(result.stderr);
}
