// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. 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:async';

import 'package:gardening/src/luci.dart';
import 'package:gardening/src/luci_services.dart';
import 'package:gardening/src/logger.dart';
import 'package:gardening/src/cache_new.dart';
import 'package:args/args.dart';

ArgParser setupArgs() {
  return new ArgParser()
    ..addOption("client",
        abbr: "c", defaultsTo: 'client.dart', help: "Set which client to use.")
    ..addFlag("verbose",
        abbr: "v", negatable: false, help: "Print debugging information.")
    ..addFlag("no-cache",
        negatable: false,
        defaultsTo: false,
        help: "Use this flag to bypass caching. This may be slower.")
    ..addFlag("help",
        negatable: false,
        help: "Shows information on how to use the luci tool.")
    ..addFlag("build-bots",
        negatable: false,
        help: "Use this flag to see the primary build bots for --client.")
    ..addFlag("build-bots-all",
        negatable: false,
        help: "Use this flag to see all build bots for --client.")
    ..addFlag("master",
        negatable: false,
        help: "Use this flag to see information about master for --client.")
    ..addFlag("build-groups",
        negatable: false,
        help: "Use this flag to see all builder-groups not -dev, -stable "
            "or -integration for --client.")
    ..addFlag("builders-in-group",
        negatable: false,
        help: "Use this flag as `--build-bot-details <group>` to see all "
            "builders (incl. shards) for a build group <group>.")
    ..addFlag("build-bot-details",
        negatable: false,
        help: "Use this flag as `--build-bot-details <name>` where "
            "<name> is the name of the build bot, to see details of "
            "a specific build bot.")
    ..addFlag("build-details",
        negatable: false,
        help: "use this option as `--build-details <name> <buildNo>` where "
            "<name> is the name of the bot and "
            "<buildNo> is the number of the build.")
    ..addFlag("builds-with-commit",
        negatable: false,
        help: "Fetches all builds with a specific commit. Use this flag as "
            "`--builds-with-commit <commit-hash>` where the <commit-hash> is "
            "the hash of the commit");
}

void printHelp(ArgParser parser) {
  print("This tool calls different pages on Luci and aggregate the information "
      "found. Below is stated information about flags and options:");
  print("");
  print(parser.usage);
}

main(List<String> args) async {
  var parser = setupArgs();
  var results = parser.parse(args);

  if (results["help"]) {
    printHelp(parser);
    return;
  }

  var luci = new Luci();
  Logger logger =
      new StdOutLogger(results['verbose'] ? Level.debug : Level.info);
  CreateCacheFunction createCache = results['no-cache']
      ? noCache()
      : initCache(Uri.base.resolve('temp/gardening-cache/'), logger);

  if (results["build-bots"]) {
    await performBuildBotsPrimary(luci, createCache, results);
  } else if (results["build-bots-all"]) {
    await performBuildBotsAll(luci, createCache, results);
  } else if (results["master"]) {
    await performMaster(luci, createCache, results);
  } else if (results["build-groups"]) {
    await performBuilderGroups(luci, createCache, results);
  } else if (results["builders-in-group"]) {
    await performBuildersInGroup(luci, createCache, results);
  } else if (results["build-bot-details"]) {
    await performBuildBotDetails(luci, createCache, results);
  } else if (results["build-details"]) {
    await performBuildDetails(luci, createCache, results);
  } else if (results["builds-with-commit"]) {
    await performFindBuildsForCommit(luci, createCache, logger, results);
  } else {
    printHelp(parser);
  }

  luci.close();
}

Future performBuildBotsPrimary(
    Luci luci, CreateCacheFunction createCache, ArgResults results) async {
  var res = await getPrimaryBuilders(
      luci, results['client'], createCache(duration: new Duration(hours: 1)));
  res.fold((ex, stackTrace) {
    print(ex);
    print(stackTrace);
  }, (bots) => bots.forEach(print));
}

Future performBuildBotsAll(
    Luci luci, CreateCacheFunction cache, ArgResults results) async {
  var res = await getAllBuilders(
      luci, results['client'], cache(duration: new Duration(hours: 1)));
  res.fold((ex, stackTrace) {
    print(ex);
    print(stackTrace);
  }, (bots) => bots.forEach(print));
}

Future performMaster(
    Luci luci, CreateCacheFunction cache, ArgResults results) async {
  var res = await luci.getMaster(
      results['client'], cache(duration: new Duration(minutes: 15)));
  res.fold((ex, stackTrace) {
    print(ex);
    print(stackTrace);
  }, (res) => print(res));
}

Future performBuilderGroups(
    Luci luci, CreateCacheFunction cache, ArgResults results) async {
  var res = await getBuilderGroups(
      luci, results['client'], cache(duration: new Duration(minutes: 15)));
  res.fold((ex, stackTrace) {
    print(ex);
    print(stackTrace);
  }, (res) => res.forEach(print));
}

Future performBuildersInGroup(
    Luci luci, CreateCacheFunction cache, ArgResults results) async {
  if (results.rest.length == 0) {
    print("No argument given for <group>. To see help, use --help");
    return;
  }

  var res = await getBuildersInBuilderGroup(luci, results['client'],
      cache(duration: new Duration(minutes: 15)), results.rest[0]);
  res.fold((ex, stackTrace) {
    print(ex);
    print(stackTrace);
  }, (res) => res.forEach(print));
}

Future performBuildBotDetails(
    Luci luci, CreateCacheFunction cache, ArgResults results) async {
  if (results.rest.length == 0) {
    print("No argument given for <name>. To see help, use --help");
    return;
  }
  var result = await luci.getBuildBotDetails(results['client'], results.rest[0],
      cache(duration: new Duration(minutes: 15)));
  result.fold((ex, stackTrace) {
    print(ex);
    print(stackTrace);
  }, (detail) => print(detail));
}

Future performBuildDetails(
    Luci luci, CreateCacheFunction createCache, ArgResults results) async {
  if (results.rest.length < 2) {
    print("Missing argument for <name> or <buildNo>. To see help, use --help");
    return;
  }
  int buildNumber = int.parse(results.rest[1], onError: (source) => 0);
  if (buildNumber <= 0) {
    print("The buildnumber ${results['build-details']} must be a integer "
        "greater than zero");
    return;
  }

  var result = await luci.getBuildBotBuildDetails(
      results['client'],
      results.rest[0],
      buildNumber,
      createCache(duration: new Duration(minutes: 15)));
  result.fold((ex, stackTrace) {
    print(ex);
    print(stackTrace);
  }, (detail) => print(detail));
}

Future performFindBuildsForCommit(Luci luci, CreateCacheFunction createCache,
    Logger logger, ArgResults results) async {
  if (results.rest.length == 0) {
    print("Missing argument for <commit>. To see help, use --help");
    return;
  }

  int amount = 25;
  logger.info(
      "Sorry - this is going to take some time, since we have to look into all "
      "$amount latest builds for all bots for client ${results['client']}.\n"
      "Subsequent queries run faster if caching is not turned off...");

  var result = await fetchBuildsForCommmit(
      luci, logger, results['client'], results.rest[0], createCache, amount);
  result.fold((ex, st) {
    print(ex);
    print(st);
  }, (List<BuildDetail> details) {
    print("The commit '${results.rest[0]} is used in the following builds:");
    details.forEach((detail) {
      String url = "https://luci-milo.appspot.com/buildbot/"
          "${detail.client}/${detail.botName}/${detail.buildNumber}";
      print("${detail.botName}: #${detail.buildNumber}\t$url");
    });
  });
}
