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

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