// Copyright (c) 2015, 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.

/// A CLI tool to generate documentation for packages from pub.dartlang.org.
library dartdoc.doc_packages;

import 'dart:async';
import 'dart:convert' show JSON, UTF8;
import 'dart:io';

import 'package:args/args.dart';
import 'package:http/http.dart' as http;
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';

// TODO: Use isolates; Platform.numberOfProcessors.

const String _rootDir = 'pub.dartlang.org';

/// To use:
///
///     dart tool/doc_packages.dart foo_package bar_package
///
/// or:
///
///     dart tool/doc_packages.dart --list --page=1
///
/// or:
///
///     dart tool/doc_packages.dart --generate --page=3
///
void main(List<String> _args) {
  var parser = _createArgsParser();
  var args = parser.parse(_args);

  if (args['help']) {
    _printUsageAndExit(parser);
  } else if (args['list']) {
    performList(int.parse(args['page']));
  } else if (args['generate']) {
    performGenerate(int.parse(args['page']));
  } else if (args.rest.isEmpty) {
    _printUsageAndExit(parser, exitCode: 1);
  } else {
    // Handle args.rest.
    generateForPackages(args.rest);
  }
}

ArgParser _createArgsParser() {
  var parser = new ArgParser();
  parser.addFlag('help',
      abbr: 'h', negatable: false, help: 'Show command help.');
  parser.addFlag('list', help: 'Show available pub packages', negatable: false);
  parser.addFlag('generate',
      help: 'Generate docs for available pub packages.', negatable: false);
  parser.addOption('page',
      help: 'The pub.dartlang.org page to list or generate for.',
      defaultsTo: '1');
  return parser;
}

/// Print help if we are passed the help option or invalid arguments.
void _printUsageAndExit(ArgParser parser, {int exitCode: 0}) {
  print('Generate documentation for published pub packages.\n');
  print('Usage: _doc_packages [OPTIONS] <package1> <package2>\n');
  print(parser.usage);
  exit(exitCode);
}

void performList(int page) {
  print('Listing pub packages for page ${page}');
  print('');

  _packageUrls(page).then((List<String> packages) {
    return _getPackageInfos(packages).then((List<PackageInfo> infos) {
      infos.forEach(print);
    });
  });
}

void performGenerate(int page) {
  print('Generating docs for page ${page} into ${_rootDir}/');
  print('');

  _packageUrls(page).then((List<String> packages) {
    return _getPackageInfos(packages).then((List<PackageInfo> infos) {
      return Future.forEach(infos, (info) {
        return _printGenerationResult(info, _generateFor(info));
      });
    });
  });
}

void generateForPackages(List<String> packages) {
  print('Generating docs into ${_rootDir}/');
  print('');

  List<String> urls = packages
      .map((s) => 'https://pub.dartlang.org/packages/${s}.json')
      .toList();

  _getPackageInfos(urls).then((List<PackageInfo> infos) {
    return Future.forEach(infos, (PackageInfo info) {
      return _printGenerationResult(info, _generateFor(info));
    });
  });
}

Future _printGenerationResult(PackageInfo package, Future generationResult) {
  String name = package.name.padRight(20);

  return generationResult.then((bool result) {
    if (result) {
      print('${name}: passed');
    } else {
      print('${name}: (skipped)');
    }
  }).catchError((e) {
    print('${name}: * failed *');
  });
}

Future<List<String>> _packageUrls(int page) {
  return http
      .get('https://pub.dartlang.org/packages.json?page=${page}')
      .then((response) {
    return JSON.decode(response.body)['packages'];
  });
}

Future<List<PackageInfo>> _getPackageInfos(List<String> packageUrls) {
  List<Future> futures = packageUrls.map((String p) {
    return http.get(p).then((response) {
      var json = JSON.decode(response.body);
      String name = json['name'];
      List<Version> versions =
          json['versions'].map((v) => new Version.parse(v)).toList();
      return new PackageInfo(name, Version.primary(versions));
    });
  }).toList();

  return Future.wait(futures);
}

StringBuffer _logBuffer;

/// Generate the docs for the given package into _rootDir. Return whether
/// generation was performed or was skipped (due to an older package).
Future<bool> _generateFor(PackageInfo package) async {
  _logBuffer = new StringBuffer();

  // Get the package archive (tar zxvf foo.tar.gz).
  var response = await http.get(package.archiveUrl);
  if (response.statusCode != 200) throw response;

  Directory output = new Directory('${_rootDir}/${package.name}');
  output.createSync(recursive: true);

  try {
    new File(output.path + '/archive.tar.gz')
        .writeAsBytesSync(response.bodyBytes);

    await _exec('tar', ['zxvf', 'archive.tar.gz'],
        cwd: output.path, quiet: true);

    // Rule out any old packages (old sdk constraints).
    File pubspecFile = new File(output.path + '/pubspec.yaml');
    var pubspecInfo = loadYaml(pubspecFile.readAsStringSync());

    // Check for old versions.
    if (_isOldSdkConstraint(pubspecInfo)) {
      _log('skipping ${package.name} - non-matching sdk constraint');
      return false;
    }

    // Run pub get.
    await _exec('pub', ['get'],
        cwd: output.path, timeout: new Duration(seconds: 30));

    // Run dartdoc.
    await _exec('dart', ['../../bin/dartdoc.dart'], cwd: output.path);

    return true;
  } catch (e, st) {
    _log(e.toString());
    _log(st.toString());
    rethrow;
  } finally {
    new File(output.path + '/output.txt')
        .writeAsStringSync(_logBuffer.toString());
  }
}

Future _exec(String command, List<String> args, {String cwd, bool quiet: false,
    Duration timeout: const Duration(seconds: 60)}) {
  return Process
      .start(command, args, workingDirectory: cwd)
      .then((Process process) {
    if (!quiet) {
      process.stdout.listen((bytes) => _log(UTF8.decode(bytes)));
      process.stderr.listen((bytes) => _log(UTF8.decode(bytes)));
    }

    Future f = process.exitCode.then((code) {
      if (code != 0) throw code;
    });

    if (timeout != null) {
      return f.timeout(timeout, onTimeout: () {
        _log('Timing out operation ${command}.');
        process.kill();
        throw 'timeout on ${command}';
      });
    } else {
      return f;
    }
  });
}

bool _isOldSdkConstraint(var pubspecInfo) {
  var environment = pubspecInfo['environment'];
  if (environment != null) {
    var sdk = environment['sdk'];
    if (sdk != null) {
      VersionConstraint constraint = new VersionConstraint.parse(sdk);
      String version = Platform.version;
      if (version.contains(' ')) version =
          version.substring(0, version.indexOf(' '));
      if (!constraint.allows(new Version.parse(version))) {
        _log('sdk constraint = ${constraint}');
        return true;
      } else {
        return false;
      }
    }
  }

  return false;
}

void _log(String str) {
  _logBuffer.write(str);
}

class PackageInfo {
  final String name;
  final Version version;

  PackageInfo(this.name, this.version);

  String get archiveUrl =>
      'https://storage.googleapis.com/pub.dartlang.org/packages/${name}-${version}.tar.gz';

  String toString() => '${name}, ${version}';
}
