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

/// Definitions used to run the polymer linter and deploy tools without using
/// pub serve or pub deploy.
library polymer.src.build.runner;

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

import 'package:barback/barback.dart';
import 'package:path/path.dart' as path;
import 'package:stack_trace/stack_trace.dart';
import 'package:yaml/yaml.dart';


/// Collects different parameters needed to configure and run barback.
class BarbackOptions {
  /// Phases of transformers to run for the current package.
  /// Use packagePhases to specify phases for other packages.
  final List<List<Transformer>> phases;

  /// Package to treat as the current package in barback.
  final String currentPackage;

  /// Directory root for the current package.
  final String packageHome;

  /// Mapping between package names and the path in the file system where
  /// to find the sources of such package.
  final Map<String, String> packageDirs;

  /// Whether to run transformers on the test folder.
  final bool transformTests;

  /// Directory where to generate code, if any.
  final String outDir;

  /// Whether to print error messages using a json-format that tools, such as
  /// the Dart Editor, can process.
  final bool machineFormat;

  /// Whether to follow symlinks when listing directories. By default this is
  /// false because directories have symlinks for the packages directory created
  /// by pub, but it can be turned on for custom uses of this library.
  final bool followLinks;

  /// Phases of transformers to apply to packages other than the current
  /// package, keyed by the package name.
  final Map<String, List<List<Transformer>>> packagePhases;

  BarbackOptions(this.phases, this.outDir, {currentPackage, String packageHome,
      packageDirs, this.transformTests: false, this.machineFormat: false,
      this.followLinks: false,
      this.packagePhases: const {}})
      : currentPackage = (currentPackage != null
          ? currentPackage : readCurrentPackageFromPubspec()),
        packageHome = packageHome,
        packageDirs = (packageDirs != null
          ? packageDirs : readPackageDirsFromPub(packageHome, currentPackage));

}

/// Creates a barback system as specified by [options] and runs it.  Returns a
/// future that contains the list of assets generated after barback runs to
/// completion.
Future<AssetSet> runBarback(BarbackOptions options) {
  var barback = new Barback(new _PackageProvider(options.packageDirs));
  _initBarback(barback, options);
  _attachListeners(barback, options);
  if (options.outDir == null) return barback.getAllAssets();
  return _emitAllFiles(barback, options);
}

/// Extract the current package from the pubspec.yaml file.
String readCurrentPackageFromPubspec([String dir]) {
  var pubspec = new File(
      dir == null ? 'pubspec.yaml' : path.join(dir, 'pubspec.yaml'));
  if (!pubspec.existsSync()) {
    print('error: pubspec.yaml file not found, please run this script from '
        'your package root directory.');
    return null;
  }
  return loadYaml(pubspec.readAsStringSync())['name'];
}

/// Extract a mapping between package names and the path in the file system
/// which has the source of the package. This map will contain an entry for the
/// current package and everything it depends on (extracted via `pub
/// list-package-dirs`).
Map<String, String> readPackageDirsFromPub(
    [String packageHome, String currentPackage]) {
  var cachedDir = Directory.current;
  if (packageHome != null) {
    Directory.current = new Directory(packageHome);
  } else {
    packageHome = cachedDir.path;
  }

  var dartExec = Platform.executable;
  // If dartExec == dart, then dart and pub are in standard PATH.
  var sdkDir = dartExec == 'dart' ? '' : path.dirname(dartExec);
  var pub = path.join(sdkDir, Platform.isWindows ? 'pub.bat' : 'pub');
  var result = Process.runSync(pub, ['list-package-dirs']);
  if (result.exitCode != 0) {
    print("unexpected error invoking 'pub':");
    print(result.stdout);
    print(result.stderr);
    exit(result.exitCode);
  }
  var map = JSON.decode(result.stdout)["packages"];
  map.forEach((k, v) { map[k] = path.absolute(packageHome, path.dirname(v)); });

  if (currentPackage == null) {
    currentPackage = readCurrentPackageFromPubspec(packageHome);
  }
  map[currentPackage] = packageHome;

  Directory.current = cachedDir;
  return map;
}

/// Return the relative path of each file under [subDir] in [package].
Iterable<String> _listPackageDir(String package, String subDir,
    BarbackOptions options) {
  var packageDir = options.packageDirs[package];
  if (packageDir == null) return const [];
  var dir = new Directory(path.join(packageDir, subDir));
  if (!dir.existsSync()) return const [];
  return dir.listSync(recursive: true, followLinks: options.followLinks)
      .where((f) => f is File)
      .map((f) => path.relative(f.path, from: packageDir));
}

/// A simple provider that reads files directly from the pub cache.
class _PackageProvider implements PackageProvider {
  Map<String, String> packageDirs;
  Iterable<String> get packages => packageDirs.keys;

  _PackageProvider(this.packageDirs);

  Future<Asset> getAsset(AssetId id) => new Future.value(
      new Asset.fromPath(id, path.join(packageDirs[id.package],
      _toSystemPath(id.path))));
}

/// Convert asset paths to system paths (Assets always use the posix style).
String _toSystemPath(String assetPath) {
  if (path.Style.platform != path.Style.windows) return assetPath;
  return path.joinAll(path.posix.split(assetPath));
}

/// Tell barback which transformers to use and which assets to process.
void _initBarback(Barback barback, BarbackOptions options) {
  var assets = [];
  void addAssets(String package, String subDir) {
    for (var filepath in _listPackageDir(package, subDir, options)) {
      assets.add(new AssetId(package, filepath));
    }
  }

  for (var package in options.packageDirs.keys) {
    // Notify barback to process anything under 'lib' and 'asset'.
    addAssets(package, 'lib');
    addAssets(package, 'asset');

    if (options.packagePhases.containsKey(package)) {
      barback.updateTransformers(package, options.packagePhases[package]);
    }
  }
  barback.updateTransformers(options.currentPackage, options.phases);

  // In case of the current package, include also 'web'.
  addAssets(options.currentPackage, 'web');
  if (options.transformTests) addAssets(options.currentPackage, 'test');

  // Add the sources after the transformers so all transformers are present
  // when barback starts processing the assets.
  barback.updateSources(assets);
}

/// Attach error listeners on [barback] so we can report errors.
void _attachListeners(Barback barback, BarbackOptions options) {
  // Listen for errors and results
  barback.errors.listen((e) {
    var trace = null;
    if (e is Error) trace = e.stackTrace;
    if (trace != null) {
      print(Trace.format(trace));
    }
    print('error running barback: $e');
    exit(1);
  });

  barback.results.listen((result) {
    if (!result.succeeded) {
      print("build failed with errors: ${result.errors}");
      exit(1);
    }
  });

  barback.log.listen((entry) {
    if (options.machineFormat) {
      print(_jsonFormatter(entry));
    } else {
      print(_consoleFormatter(entry));
    }
  });
}

/// Emits all outputs of [barback] and copies files that we didn't process (like
/// dependent package's libraries).
Future _emitAllFiles(Barback barback, BarbackOptions options) {
  return barback.getAllAssets().then((assets) {
    // Delete existing output folder before we generate anything
    var dir = new Directory(options.outDir);
    if (dir.existsSync()) dir.deleteSync(recursive: true);
    return _emitPackagesDir(options)
      .then((_) => _emitTransformedFiles(assets, options))
      .then((_) => _addPackagesSymlinks(assets, options))
      .then((_) => assets);
  });
}

Future _emitTransformedFiles(AssetSet assets, BarbackOptions options) {
  // Copy all the assets we transformed
  var futures = [];
  var currentPackage = options.currentPackage;
  var transformTests = options.transformTests;
  var outPackages = path.join(options.outDir, 'packages');

  return Future.forEach(assets, (asset) {
    var id = asset.id;
    var dir = _firstDir(id.path);
    if (dir == null) return null;

    var filepath;
    if (dir == 'lib') {
      // Put lib files directly under the packages folder (e.g. 'lib/foo.dart'
      // will be emitted at out/packages/package_name/foo.dart).
      filepath = path.join(outPackages, id.package,
          _toSystemPath(id.path.substring(4)));
    } else if (id.package == currentPackage &&
        (dir == 'web' || (transformTests && dir == 'test'))) {
      filepath = path.join(options.outDir, _toSystemPath(id.path));
    } else {
      // TODO(sigmund): do something about other assets?
      return null;
    }

    return _writeAsset(filepath, asset);
  });
}

/// Adds a package symlink from each directory under `out/web/foo/` to
/// `out/packages`.
void _addPackagesSymlinks(AssetSet assets, BarbackOptions options) {
  var outPackages = path.join(options.outDir, 'packages');
  var currentPackage = options.currentPackage;
  for (var asset in assets) {
    var id = asset.id;
    if (id.package != currentPackage) continue;
    var firstDir = _firstDir(id.path);
    if (firstDir == null) continue;

    if (firstDir == 'web' || (options.transformTests && firstDir == 'test')) {
      var dir = path.join(options.outDir, path.dirname(_toSystemPath(id.path)));
      var linkPath = path.join(dir, 'packages');
      var link = new Link(linkPath);
      if (!link.existsSync()) {
        var targetPath = Platform.operatingSystem == 'windows'
            ? path.normalize(path.absolute(outPackages))
            : path.normalize(path.relative(outPackages, from: dir));
        link.createSync(targetPath);
      }
    }
  }
}

/// Emits a 'packages' directory directly under `out/packages` with the contents
/// of every file that was not transformed by barback.
Future _emitPackagesDir(BarbackOptions options) {
  var outPackages = path.join(options.outDir, 'packages');
  _ensureDir(outPackages);

  // Copy all the files we didn't process
  var dirs = options.packageDirs;

  return Future.forEach(dirs.keys, (package) {
    return Future.forEach(_listPackageDir(package, 'lib', options), (relpath) {
      var inpath = path.join(dirs[package], relpath);
      var outpath = path.join(outPackages, package, relpath.substring(4));
      return _copyFile(inpath, outpath);
    });
  });
}

/// Ensure [dirpath] exists.
void _ensureDir(String dirpath) {
  new Directory(dirpath).createSync(recursive: true);
}

/// Returns the first directory name on a url-style path, or null if there are
/// no slashes.
String _firstDir(String url) {
  var firstSlash = url.indexOf('/');
  if (firstSlash == -1) return null;
  return url.substring(0, firstSlash);
}

/// Copy a file from [inpath] to [outpath].
Future _copyFile(String inpath, String outpath) {
  _ensureDir(path.dirname(outpath));
  return new File(inpath).openRead().pipe(new File(outpath).openWrite());
}

/// Write contents of an [asset] into a file at [filepath].
Future _writeAsset(String filepath, Asset asset) {
  _ensureDir(path.dirname(filepath));
  return asset.read().pipe(new File(filepath).openWrite());
}

String _kindFromEntry(LogEntry entry) {
  var level = entry.level;
  return level == LogLevel.ERROR ? 'error'
      : (level == LogLevel.WARNING ? 'warning' : 'info');
}

/// Formatter that generates messages using a format that can be parsed
/// by tools, such as the Dart Editor, for reporting error messages.
String _jsonFormatter(LogEntry entry) {
  var kind = _kindFromEntry(entry);
  var span = entry.span;
  return JSON.encode((span == null)
      ? [{'method': kind, 'params': {'message': entry.message}}]
      : [{'method': kind,
          'params': {
            'file': span.sourceUrl,
            'message': entry.message,
            'line': span.start.line + 1,
            'charStart': span.start.offset,
            'charEnd': span.end.offset,
          }}]);
}

/// Formatter that generates messages that are easy to read on the console (used
/// by default).
String _consoleFormatter(LogEntry entry) {
  var kind = _kindFromEntry(entry);
  var useColors = stdioType(stdout) == StdioType.TERMINAL;
  var levelColor = (kind == 'error') ? _RED_COLOR : _MAGENTA_COLOR;
  var output = new StringBuffer();
  if (useColors) output.write(levelColor);
  output..write(kind)..write(' ');
  if (useColors) output.write(_NO_COLOR);
  if (entry.span == null) {
    output.write(entry.message);
  } else {
    output.write(entry.span.getLocationMessage(entry.message,
          useColors: useColors,
          color: levelColor));
  }
  return output.toString();
}

const String _RED_COLOR = '\u001b[31m';
const String _MAGENTA_COLOR = '\u001b[35m';
const String _NO_COLOR = '\u001b[0m';
