// 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.
library initialize.transformer;

import 'dart:async';
import 'dart:collection' show Queue;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/assets.dart';
import 'package:code_transformers/resolver.dart';
import 'package:code_transformers/src/dart_sdk.dart' as dart_sdk;
import 'package:dart_style/dart_style.dart';
import 'package:glob/glob.dart';
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' show parse;
import 'package:path/path.dart' as path;

import 'build/initializer_plugin.dart';
export 'build/initializer_plugin.dart';

/// Create a new [Asset] which inlines your [Initializer] annotations into
/// a new file that bootstraps your application.
Asset generateBootstrapFile(Resolver resolver, Transform transform,
    AssetId primaryAssetId, AssetId newEntryPointId,
    {bool errorIfNotFound: true,
    List<InitializerPlugin> plugins,
    bool appendDefaultPlugin: true}) {
  if (appendDefaultPlugin) {
    if (plugins == null) plugins = [];
    plugins.add(const DefaultInitializerPlugin());
  }
  return new _BootstrapFileBuilder(
          resolver, transform, primaryAssetId, newEntryPointId, errorIfNotFound,
          plugins: plugins)
      .run();
}

/// Transformer which removes the mirror-based initialization logic and replaces
/// it with static logic.
class InitializeTransformer extends Transformer {
  final Resolvers _resolvers;
  final Iterable<Glob> _entryPointGlobs;
  final bool _errorIfNotFound;
  final List<InitializerPlugin> plugins;

  InitializeTransformer(List<String> entryPoints,
      {bool errorIfNotFound: true, this.plugins})
      : _entryPointGlobs = entryPoints.map((e) => new Glob(e)),
        _errorIfNotFound = errorIfNotFound,
        _resolvers = new Resolvers.fromMock(dart_sdk.mockSdkSources);

  factory InitializeTransformer.asPlugin(BarbackSettings settings) =>
      new InitializeTransformer(_readFileList(settings, 'entry_points'));

  bool isPrimary(AssetId id) => _entryPointGlobs.any((g) => g.matches(id.path));

  Future apply(Transform transform) {
    if (transform.primaryInput.id.path.endsWith('.dart')) {
      return _buildBootstrapFile(transform);
    } else if (transform.primaryInput.id.path.endsWith('.html')) {
      return transform.primaryInput.readAsString().then((html) {
        var document = parse(html);
        var originalDartFile =
            _findMainScript(document, transform.primaryInput.id, transform);
        return _buildBootstrapFile(transform, primaryId: originalDartFile)
            .then((AssetId newDartFile) {
          return _replaceEntryWithBootstrap(transform, document,
              transform.primaryInput.id, originalDartFile, newDartFile);
        });
      });
    } else {
      transform.logger.warning(
          'Invalid entry point ${transform.primaryInput.id}. Must be either a '
          '.dart or .html file.');
    }
    return new Future.value();
  }

  // Returns the AssetId of the newly created bootstrap file.
  Future<AssetId> _buildBootstrapFile(Transform transform,
      {AssetId primaryId}) {
    if (primaryId == null) primaryId = transform.primaryInput.id;
    var newEntryPointId = new AssetId(primaryId.package,
        '${path.url.withoutExtension(primaryId.path)}.initialize.dart');
    return transform.hasInput(newEntryPointId).then((exists) {
      if (exists) {
        transform.logger
            .error('New entry point file $newEntryPointId already exists.');
        return null;
      }

      return _resolvers.get(transform, [primaryId]).then((resolver) {
        transform.addOutput(generateBootstrapFile(
            resolver, transform, primaryId, newEntryPointId,
            errorIfNotFound: _errorIfNotFound, plugins: plugins));
        resolver.release();
        return newEntryPointId;
      });
    });
  }

  // Finds the first (and only) dart script on an html page and returns the
  // [AssetId] that points to it
  AssetId _findMainScript(
      dom.Document document, AssetId entryPoint, Transform transform) {
    var scripts = _getScripts(document);
    if (scripts.length != 1) {
      transform.logger.error('Expected exactly one dart script in $entryPoint '
          'but found ${scripts.length}.');
      return null;
    }

    var src = _getScriptAttribute(scripts[0]);
    if (src == null) {
      // TODO(jakemac): Support inline scripts,
      transform.logger.error('Inline scripts are not supported at this time, '
          'see https://github.com/dart-lang/initialize/issues/20.');
      return null;
    }

    return uriToAssetId(
        entryPoint, src, transform.logger, scripts[0].sourceSpan);
  }

  // Replaces script tags pointing to [originalDartFile] with [newDartFile] in
  // [entryPoint].
  void _replaceEntryWithBootstrap(Transform transform, dom.Document document,
      AssetId entryPoint, AssetId originalDartFile, AssetId newDartFile) {
    var scripts = _getScripts(document).where((script) {
      var assetId = uriToAssetId(entryPoint, _getScriptAttribute(script),
          transform.logger, script.sourceSpan);
      return assetId == originalDartFile;
    }).toList();

    if (scripts.length != 1) {
      transform.logger
          .error('Expected exactly one script pointing to $originalDartFile in '
              '$entryPoint, but found ${scripts.length}.');
      return;
    }
    _setScriptAttribute(
        scripts[0],
        path.url
            .relative(newDartFile.path, from: path.dirname(entryPoint.path)));
    transform.addOutput(new Asset.fromString(entryPoint, document.outerHtml));
  }

  String _getScriptAttribute(dom.Element element) {
    switch (element.localName) {
      case 'script':
        return element.attributes['src'];
      case 'link':
        return element.attributes['href'];
      default:
        throw 'Unrecognized element $element';
    }
  }

  void _setScriptAttribute(dom.Element element, String path) {
    switch (element.localName) {
      case 'script':
        element.attributes['src'] = path;
        break;
      case 'link':
        element.attributes['href'] = path;
        break;
    }
  }

  List<dom.Element> _getScripts(dom.Document document) =>
      document.querySelectorAll(
          'script[type="application/dart"], link[rel="x-dart-test"]');
}

// Class which builds a bootstrap file.
class _BootstrapFileBuilder {
  final Resolver _resolver;
  final Transform _transform;
  final bool _errorIfNotFound;
  AssetId _entryPoint;
  AssetId _newEntryPoint;

  /// The resolved initialize library.
  LibraryElement _initializeLibrary;

  /// The resolved Initializer class from the initialize library.
  ClassElement _initializer;

  /// Queue for intialization annotations.
  final _initQueue = new Queue<InitializerData>();

  /// All the annotations we have seen for each element
  final _seenAnnotations = new Map<Element, Set<ElementAnnotation>>();

  /// The list of [InitializerPlugin]s to apply. The first plugin which asks to
  /// be applied to a given initializer is the only one that will apply.
  List<InitializerPlugin> _plugins;

  TransformLogger _logger;

  _BootstrapFileBuilder(this._resolver, this._transform, this._entryPoint,
      this._newEntryPoint, this._errorIfNotFound,
      {List<InitializerPlugin> plugins}) {
    _logger = _transform.logger;
    _initializeLibrary =
        _resolver.getLibrary(new AssetId('initialize', 'lib/initialize.dart'));
    if (_initializeLibrary != null) {
      _initializer = _initializeLibrary.getType('Initializer');
    } else if (_errorIfNotFound) {
      _logger.warning('Unable to read "package:initialize/initialize.dart". '
          'This file must be imported via $_entryPoint or a transitive '
          'dependency.');
    }
    _plugins = plugins != null ? plugins : [const DefaultInitializerPlugin()];
  }

  /// Creates and returns the new bootstrap file.
  Asset run() {
    var entryLib = _resolver.getLibrary(_entryPoint);
    _readLibraries(entryLib);

    return new Asset.fromString(_newEntryPoint, _buildNewEntryPoint(entryLib));
  }

  /// Reads Initializer annotations on this library and all its dependencies in
  /// post-order.
  void _readLibraries(LibraryElement library, [Set<LibraryElement> seen]) {
    if (seen == null) seen = new Set<LibraryElement>();
    seen.add(library);

    // Visit all our dependencies.
    for (var library in _sortedLibraryDependencies(library)) {
      // Don't include anything from the sdk.
      if (library.isInSdk) continue;
      if (seen.contains(library)) continue;
      _readLibraries(library, seen);
    }

    // Read annotations in this order: library, top level methods, classes.
    _readAnnotations(library);
    for (var method in _topLevelMethodsOfLibrary(library, seen)) {
      _readAnnotations(method);
    }
    for (var clazz in _classesOfLibrary(library, seen)) {
      readSuperClassAnnotations(InterfaceType superClass) {
        if (superClass == null) return;
        readSuperClassAnnotations(superClass.superclass);
        if (_readAnnotations(superClass.element) &&
            superClass.element.library != clazz.library) {
          _logger.warning(
              'We have detected a cycle in your import graph when running '
              'initializers on ${clazz.name}. This means the super class '
              '${superClass.name} has a dependency on this library '
              '(possibly transitive).');
        }
      }

      readSuperClassAnnotations(clazz.supertype);
      _readAnnotations(clazz);
    }
  }

  bool _readAnnotations(Element element) {
    var found = false;
    // analyzer 0.29 doesn't allow this optimization :
    //if (element.metadata.isEmpty) return found;

    var metaNodes;
    var node = element.computeNode();
    if (node is SimpleIdentifier && node.parent is LibraryIdentifier) {
      metaNodes = (node.parent.parent as AnnotatedNode).metadata;
    } else if (node is ClassDeclaration || node is FunctionDeclaration) {
      metaNodes = (node as AnnotatedNode).metadata;
    } else {
      return found;
    }

    metaNodes.where((Annotation metaNode) {
      // First filter out anything that is not a Initializer.
      var meta = metaNode.elementAnnotation;
      var e = meta.element;
      if (e is PropertyAccessorElement) {
        // 'as dynamic' is because evaluationResult is a property on an impl class, e.g. one that
        // isn't supposed to be used externally.
        return _isInitializer(
            (e.variable as dynamic).evaluationResult.value.type);
      } else if (e is ConstructorElement) {
        return _isInitializer(e.returnType);
      }
      return false;
    }).where((Annotation metaNode) {
      var meta = metaNode.elementAnnotation;
      _seenAnnotations.putIfAbsent(element, () => new Set<ElementAnnotation>());
      return !_seenAnnotations[element].contains(meta);
    }).forEach((Annotation metaNode) {
      var meta = metaNode.elementAnnotation;
      _seenAnnotations[element].add(meta);
      _initQueue.addLast(new InitializerData._(node, metaNode));
      found = true;
    });
    return found;
  }

  String _buildNewEntryPoint(LibraryElement entryLib) {
    var importsBuffer = new StringBuffer();
    var initializersBuffer = new StringBuffer();
    var libraryPrefixes = new Map<LibraryElement, String>();

    // Import the static_loader, initializer, and original entry point.
    importsBuffer
        .writeln("import 'package:initialize/src/static_loader.dart';");
    importsBuffer.writeln("import 'package:initialize/initialize.dart';");
    libraryPrefixes[entryLib] = 'i0';

    initializersBuffer.writeln('initializers.addAll([');
    while (_initQueue.isNotEmpty) {
      var next = _initQueue.removeFirst();

      libraryPrefixes.putIfAbsent(
          next.targetElement.library, () => 'i${libraryPrefixes.length}');
      libraryPrefixes.putIfAbsent(next.annotationElement.element.library,
          () => 'i${libraryPrefixes.length}');

      // Run the first plugin which asks to be ran and then stop.
      var data = new InitializerPluginData(
          next, _newEntryPoint, libraryPrefixes, _resolver, _logger);
      var plugin = _plugins.firstWhere((p) => p.shouldApply(data), orElse: () {
        _logger.error('No InitializerPlugin handled the annotation: '
            '${next.annotationElement} on: ${next.targetElement}.');
      });
      if (plugin == null) continue;

      var text = plugin.apply(data);
      if (text != null) initializersBuffer.writeln('$text,');
    }
    initializersBuffer.writeln(']);');

    libraryPrefixes
        .forEach((lib, prefix) => _writeImport(lib, prefix, importsBuffer));

    // TODO(jakemac): copyright and library declaration
    return new DartFormatter().format('''
$importsBuffer
main() {
$initializersBuffer
  return i0.main();
}
''');
  }

  _writeImport(LibraryElement lib, String prefix, StringBuffer buffer) {
    AssetId id = (lib.source as dynamic).assetId;

    if (id.path.startsWith('lib/')) {
      var packagePath = id.path.replaceFirst('lib/', '');
      buffer.write("import 'package:${id.package}/${packagePath}'");
    } else if (id.package != _newEntryPoint.package) {
      _logger.error("Can't import `${id}` from `${_newEntryPoint}`");
    } else if (path.url.split(id.path)[0] ==
        path.url.split(_newEntryPoint.path)[0]) {
      var relativePath = path.url
          .relative(id.path, from: path.url.dirname(_newEntryPoint.path));
      buffer.write("import '${relativePath}'");
    } else {
      _logger.error("Can't import `${id}` from `${_newEntryPoint}`");
    }
    buffer.writeln(' as $prefix;');
  }

  bool _isInitializer(InterfaceType type) {
    // If `_initializer` wasn't found then it was never loaded (even
    // transitively), and so no annotations can be initializers.
    if (_initializer == null) return false;
    if (type == null) return false;
    if (type.element.type == _initializer.type) return true;
    if (_isInitializer(type.superclass)) return true;
    for (var interface in type.interfaces) {
      if (_isInitializer(interface)) return true;
    }
    return false;
  }

  /// Retrieves all top-level methods that are visible if you were to import
  /// [lib]. This includes exported methods from other libraries too.
  List<FunctionElement> _topLevelMethodsOfLibrary(
      LibraryElement library, Set<LibraryElement> seen) {
    var methods = [];

    var orderedExports = new List.from(library.exports)
      ..sort((a, b) => a.uriOffset.compareTo(b.uriOffset));
    for (var export in orderedExports) {
      if (seen.contains(export.exportedLibrary)) continue;
      methods.addAll(_topLevelMethodsOfLibrary(export.exportedLibrary, seen));
    }

    for (CompilationUnitElement unit in _orderedUnits(library)) {
      methods.addAll(new List.from(unit.functions)
        ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset)));
    }

    return methods;
  }

  /// Retrieves all classes that are visible if you were to import [lib]. This
  /// includes exported classes from other libraries.
  List<ClassElement> _classesOfLibrary(
      LibraryElement library, Set<LibraryElement> seen) {
    var classes = [];

    var orderedExports = new List.from(library.exports)
      ..sort((a, b) => a.uriOffset.compareTo(b.uriOffset));
    for (var export in orderedExports) {
      if (seen.contains(export.exportedLibrary)) continue;
      classes.addAll(_classesOfLibrary(export.exportedLibrary, seen));
    }

    for (var unit in _orderedUnits(library)) {
      classes.addAll(new List.from(unit.types)
        ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset)));
    }

    return classes;
  }

  List<CompilationUnitElement> _orderedUnits(LibraryElement library) {
    var definingUnit = library.definingCompilationUnit;
    // The first item is the source library, remove it for now.
    return new List.from(library.units)
      ..sort((a, b) {
        if (a == definingUnit) return 1;
        if (b == definingUnit) return -1;
        return a.uri.compareTo(b.uri);
      });
  }

  Iterable<LibraryElement> _sortedLibraryDependencies(LibraryElement library) {
    // TODO(jakemac): Investigate supporting annotations on part-of directives.
    getLibrary(UriReferencedElement element) {
      if (element is ImportElement) return element.importedLibrary;
      if (element is ExportElement) return element.exportedLibrary;
    }

    return (new List.from(library.imports)
          ..addAll(library.exports)
          ..sort((a, b) => a.nameOffset.compareTo(b.nameOffset)))
        .map(getLibrary);
  }
}

/// An [Initializer] annotation and the target of that annotation.
class InitializerData {
  /// The target [AstNode] of the annotation.
  final AstNode targetNode;

  /// The [Annotation] representing the annotation itself.
  final Annotation annotationNode;

  /// The [ElementAnnotation] representing the annotation itself.
  ElementAnnotation get annotationElement => annotationNode.elementAnnotation;

  /// The target [Element] of the annotation.
  Element get targetElement {
    if (targetNode is SimpleIdentifier &&
        targetNode.parent is LibraryIdentifier) {
      return (targetNode.parent.parent as LibraryDirective).element;
    } else if (targetNode is ClassDeclaration ||
        targetNode is FunctionDeclaration) {
      return (targetNode as dynamic).element;
    } else {
      return null;
    }
  }

  InitializerData._(this.targetNode, this.annotationNode);
}

// Reads a file list from a barback settings configuration field.
_readFileList(BarbackSettings settings, String field) {
  var value = settings.configuration[field];
  if (value == null) return null;
  var files = [];
  bool error;
  if (value is List) {
    files = value;
    error = value.any((e) => e is! String);
  } else if (value is String) {
    files = [value];
    error = false;
  } else {
    error = true;
  }
  if (error) {
    print('Bad value for "$field" in the initialize transformer. '
        'Expected either one String or a list of Strings.');
  }
  return files;
}
