// 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.

library pub.transformer_isolate;

import 'dart:async';
import 'dart:convert';
import 'dart:isolate';

import 'package:barback/barback.dart';
import 'package:source_span/source_span.dart';
import 'package:stack_trace/stack_trace.dart';

import '../../../asset/dart/serialize.dart';
import '../barback.dart';
import '../exceptions.dart';
import '../dart.dart' as dart;
import '../log.dart' as log;
import '../utils.dart';
import 'asset_environment.dart';
import 'barback_server.dart';
import 'foreign_transformer.dart';
import 'transformer_config.dart';
import 'transformer_id.dart';

/// A wrapper for an isolate from which transformer plugins can be instantiated.
class TransformerIsolate {
  /// The port used to communicate with the wrapped isolate.
  final SendPort _port;

  /// A map indicating the barback server URLs for each [TransformerId] that's
  /// loaded in the wrapped isolate.
  ///
  /// A barback server URL is the URL for the library that the given id
  /// identifies. For example, the URL for "polymer/src/mirrors_remover" might
  /// be "http://localhost:56234/packages/polymer/src/mirrors_remover.dart".
  final Map<TransformerId, Uri> _idsToUrls;

  /// The barback mode for this run of pub.
  final BarbackMode _mode;

  /// Spawns an isolate that loads all transformer libraries defined by [ids].
  ///
  /// This doesn't actually instantiate any transformers, since a
  /// [TransformerId] doesn't define the transformers' configuration. The
  /// transformers can be constructed using [create].
  ///
  /// If [snapshot] is passed, the isolate will be loaded from that path if it
  /// exists. Otherwise, a snapshot of the isolate's code will be saved to that
  /// path once the isolate is loaded.
  static Future<TransformerIsolate> spawn(AssetEnvironment environment,
      BarbackServer transformerServer, List<TransformerId> ids, {String snapshot}) {
    return mapFromIterableAsync(ids, value: (id) {
      return id.getAssetId(environment.barback);
    }).then((idsToAssetIds) {
      var baseUrl = transformerServer.url;
      var idsToUrls = mapMap(idsToAssetIds, value: (id, assetId) {
        var path = assetId.path.replaceFirst('lib/', '');
        return Uri.parse('package:${id.package}/$path');
      });

      var code = new StringBuffer();
      code.writeln("import 'dart:isolate';");

      for (var url in idsToUrls.values) {
        code.writeln("import '$url';");
      }

      code.writeln("import r'package:\$pub/transformer_isolate.dart';");
      code.writeln(
          "void main(_, SendPort replyTo) => loadTransformers(replyTo);");

      log.fine("Loading transformers from $ids");

      var port = new ReceivePort();
      return dart.runInIsolate(
          code.toString(),
          port.sendPort,
          packageRoot: baseUrl.resolve('packages'),
          snapshot: snapshot).then((_) => port.first).then((sendPort) {
        return new TransformerIsolate._(sendPort, environment.mode, idsToUrls);
      }).catchError((error, stackTrace) {
        if (error is! CrossIsolateException) throw error;
        if (error.type != 'IsolateSpawnException') throw error;

        // TODO(nweiz): don't parse this as a string once issues 12617 and 12689
        // are fixed.
        var firstErrorLine = error.message.split('\n')[1];

        // The isolate error message contains the fully expanded path, not the
        // "package:" URI, so we have to be liberal in what we look for in the
        // error message.
        var missingTransformer = idsToUrls.keys.firstWhere(
            (id) =>
                firstErrorLine.startsWith("Uncaught Error: Load Error: Failure getting ") &&
                    firstErrorLine.contains(idsToUrls[id].path),
            orElse: () => throw error);
        var packageUri = idToPackageUri(idsToAssetIds[missingTransformer]);

        // If there was an IsolateSpawnException and the import that actually
        // failed was the one we were loading transformers from, throw an
        // application exception with a more user-friendly message.
        fail('Transformer library "$packageUri" not found.', error, stackTrace);
      });
    });
  }

  TransformerIsolate._(this._port, this._mode, this._idsToUrls);

  /// Instantiate the transformers in the [config.id] with
  /// [config.configuration].
  ///
  /// If there are no transformers defined in the given library, this will
  /// return an empty set.
  Future<Set<Transformer>> create(TransformerConfig config) {
    return call(_port, {
      'library': _idsToUrls[config.id].toString(),
      'mode': _mode.name,
      'configuration': JSON.encode(config.configuration)
    }).then((transformers) {
      transformers = transformers.map(
          (transformer) => deserializeTransformerLike(transformer, config)).toSet();
      log.fine("Transformers from $config: $transformers");
      return transformers;
    }).catchError((error, stackTrace) {
      throw new TransformerLoadError(error, config.span);
    });
  }
}

/// An error thrown when a transformer fails to load.
class TransformerLoadError extends SourceSpanException implements
    WrappedException {
  final CrossIsolateException innerError;
  Chain get innerChain => innerError.stackTrace;

  TransformerLoadError(CrossIsolateException error, SourceSpan span)
      : innerError = error,
        super("Error loading transformer: ${error.message}", span);
}
