// 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/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/resolver.dart';
import 'package:path/path.dart' as path;

/// Removes the mirror-based initialization logic and replaces it with static
/// logic.
class InitializeTransformer extends Transformer {
  final Resolvers _resolvers;
  final String _entryPoint;
  final String _newEntryPoint;

  InitializeTransformer(this._entryPoint, this._newEntryPoint)
      : _resolvers = new Resolvers.fromMock({
        // The list of types below is derived from:
        //   * types that are used internally by the resolver (see
        //   _initializeFrom in resolver.dart).
        // TODO(jakemac): Move this into code_transformers so it can be shared.
        'dart:core': '''
            library dart.core;
            class Object {}
            class Function {}
            class StackTrace {}
            class Symbol {}
            class Type {}

            class String extends Object {}
            class bool extends Object {}
            class num extends Object {}
            class int extends num {}
            class double extends num {}
            class DateTime extends Object {}
            class Null extends Object {}

            class Deprecated extends Object {
              final String expires;
              const Deprecated(this.expires);
            }
            const Object deprecated = const Deprecated("next release");
            class _Override { const _Override(); }
            const Object override = const _Override();
            class _Proxy { const _Proxy(); }
            const Object proxy = const _Proxy();

            class List<V> extends Object {}
            class Map<K, V> extends Object {}
            ''',
        'dart:html': '''
            library dart.html;
            class HtmlElement {}
            ''',
      });

  factory InitializeTransformer.asPlugin(BarbackSettings settings) {
    var entryPoint = settings.configuration['entryPoint'];
    var newEntryPoint = settings.configuration['newEntryPoint'];
    if (newEntryPoint == null) {
      newEntryPoint = entryPoint.replaceFirst('.dart', '.bootstrap.dart');
    }
    return new InitializeTransformer(entryPoint, newEntryPoint);
  }

  bool isPrimary(AssetId id) => _entryPoint == id.path;

  Future apply(Transform transform) {
    var newEntryPointId =
        new AssetId(transform.primaryInput.id.package, _newEntryPoint);
    return transform.hasInput(newEntryPointId).then((exists) {
      if (exists) {
        transform.logger
            .error('New entry point file $newEntryPointId already exists.');
      } else {
        return _resolvers
            .get(transform)
            .then((resolver) => new _BootstrapFileBuilder(resolver, transform,
                transform.primaryInput.id, newEntryPointId).run());
      }
    });
  }
}

class _BootstrapFileBuilder {
  final Resolver _resolver;
  final Transform _transform;
  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>>();

  TransformLogger _logger;

  _BootstrapFileBuilder(
      this._resolver, this._transform, this._entryPoint, this._newEntryPoint) {
    _logger = _transform.logger;
    _initializeLibrary =
        _resolver.getLibrary(new AssetId('initialize', 'lib/initialize.dart'));
    _initializer = _initializeLibrary.getType('Initializer');
  }

  /// Adds the new entry point file to the transform. Should only be ran once.
  void run() {
    var entryLib = _resolver.getLibrary(_entryPoint);
    _readLibraries(entryLib);

    _transform.addOutput(
        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 importedLibrary in _sortedLibraryImports(library)) {
      // Don't include anything from the sdk.
      if (importedLibrary.isInSdk) continue;
      if (seen.contains(importedLibrary)) continue;
      _readLibraries(importedLibrary, 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)) {
      var superClass = clazz.supertype;
      while (superClass != null) {
        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).');
        }
        superClass = superClass.superclass;
      }
      _readAnnotations(clazz);
    }
  }

  bool _readAnnotations(Element element) {
    var found = false;
    element.metadata.where((ElementAnnotation meta) {
      // First filter out anything that is not a Initializer.
      var e = meta.element;
      if (e is PropertyAccessorElement) {
        return _isInitializer(e.variable.evaluationResult.value.type);
      } else if (e is ConstructorElement) {
        return _isInitializer(e.returnType);
      }
      return false;
    }).where((ElementAnnotation meta) {
      _seenAnnotations.putIfAbsent(element, () => new Set<ElementAnnotation>());
      return !_seenAnnotations[element].contains(meta);
    }).forEach((ElementAnnotation meta) {
      _seenAnnotations[element].add(meta);
      _initQueue.addLast(new _InitializerData(element, meta));
      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 and original entry point.
    importsBuffer
        .writeln("import 'package:initialize/src/static_loader.dart';");
    _maybeWriteImport(entryLib, libraryPrefixes, importsBuffer);

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

      _maybeWriteImport(next.element.library, libraryPrefixes, importsBuffer);
      _maybeWriteImport(
          next.annotation.element.library, libraryPrefixes, importsBuffer);

      _writeInitializer(next, libraryPrefixes, initializersBuffer);
    }
    initializersBuffer.writeln('  ]);');

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

  // Writes an import to library if it doesn't exist yet if libraries.
  _maybeWriteImport(LibraryElement library,
      Map<LibraryElement, String> libraries, StringBuffer buffer) {
    if (libraries.containsKey(library)) return;
    var prefix = 'i${libraries.length}';
    libraries[library] = prefix;
    _writeImport(library, prefix, buffer);
  }

  _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 (id.path.split(path.separator)[0] ==
        _newEntryPoint.path.split(path.separator)[0]) {
      var relativePath =
          path.relative(id.path, from: path.dirname(_newEntryPoint.path));
      buffer.write("import '${relativePath}'");
    } else {
      _logger.error("Can't import `${id}` from `${_newEntryPoint}`");
    }
    buffer.writeln(' as $prefix;');
  }

  _writeInitializer(_InitializerData data,
      Map<LibraryElement, String> libraryPrefixes, StringBuffer buffer) {
    final annotationElement = data.annotation.element;
    final element = data.element;

    final metaPrefix = libraryPrefixes[annotationElement.library];
    var elementString;
    if (element is LibraryElement) {
      elementString = '#${element.name}';
    } else if (element is ClassElement || element is FunctionElement) {
      elementString =
          '${libraryPrefixes[data.element.library]}.${element.name}';
    } else {
      _logger.error('Initializers can only be applied to top level functins, '
          'libraries, and classes.');
    }

    if (annotationElement is ConstructorElement) {
      var node = data.element.node;
      List<Annotation> astMeta;
      if (node is SimpleIdentifier) {
        astMeta = node.parent.parent.metadata;
      } else if (node is ClassDeclaration || node is FunctionDeclaration) {
        astMeta = node.metadata;
      } else {
        _logger.error(
            'Initializer annotations are only supported on libraries, classes, '
            'and top level methods. Found $node.');
      }
      final annotation =
          astMeta.firstWhere((m) => m.elementAnnotation == data.annotation);
      final clazz = annotation.name;
      final constructor = annotation.constructorName == null
          ? ''
          : '.${annotation.constructorName}';
      // TODO(jakemac): Support more than raw values here
      // https://github.com/dart-lang/static_init/issues/5
      final args = annotation.arguments;
      buffer.write('''
    new InitEntry(const $metaPrefix.${clazz}$constructor$args, $elementString),
''');
    } else if (annotationElement is PropertyAccessorElement) {
      buffer.write('''
    new InitEntry($metaPrefix.${annotationElement.name}, $elementString),
''');
    }
  }

  bool _isInitializer(InterfaceType type) {
    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 result = [];
    result.addAll(library.units.expand((u) => u.functions));
    for (var export in library.exports) {
      if (seen.contains(export.exportedLibrary)) continue;
      var exported = _topLevelMethodsOfLibrary(export.exportedLibrary, seen);
      _filter(exported, export.combinators);
      result.addAll(exported);
    }
    result.sort((a, b) => a.name.compareTo(b.name));
    return result;
  }

  /// 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 result = [];
    result.addAll(library.units.expand((u) => u.types));
    for (var export in library.exports) {
      if (seen.contains(export.exportedLibrary)) continue;
      var exported = _classesOfLibrary(export.exportedLibrary, seen);
      _filter(exported, export.combinators);
      result.addAll(exported);
    }
    result.sort((a, b) => a.name.compareTo(b.name));
    return result;
  }

  /// Filters [elements] that come from an export, according to its show/hide
  /// combinators. This modifies [elements] in place.
  void _filter(List<Element> elements, List<NamespaceCombinator> combinators) {
    for (var c in combinators) {
      if (c is ShowElementCombinator) {
        var show = c.shownNames.toSet();
        elements.retainWhere((e) => show.contains(e.displayName));
      } else if (c is HideElementCombinator) {
        var hide = c.hiddenNames.toSet();
        elements.removeWhere((e) => hide.contains(e.displayName));
      }
    }
  }

  Iterable<LibraryElement> _sortedLibraryImports(LibraryElement library) =>
      (new List.from(library.imports)
    ..sort((ImportElement a, ImportElement b) {
      // dart: imports don't have a uri
      if (a.uri == null && b.uri != null) return -1;
      if (b.uri == null && a.uri != null) return 1;
      if (a.uri == null && b.uri == null) {
        return a.importedLibrary.name.compareTo(b.importedLibrary.name);
      }

      // package: imports next
      var aIsPackage = a.uri.startsWith('package:');
      var bIsPackage = b.uri.startsWith('package:');
      if (aIsPackage && !bIsPackage) {
        return -1;
      } else if (bIsPackage && !aIsPackage) {
        return 1;
      } else if (bIsPackage && aIsPackage) {
        return a.uri.compareTo(b.uri);
      }

      // And finally compare based on the relative uri if both are file paths.
      var aUri = path.relative(a.source.uri.path,
          from: path.dirname(library.source.uri.path));
      var bUri = path.relative(b.source.uri.path,
          from: path.dirname(library.source.uri.path));
      return aUri.compareTo(bUri);
    })).map((import) => import.importedLibrary);
}

// Element/ElementAnnotation pair.
class _InitializerData {
  final Element element;
  final ElementAnnotation annotation;

  _InitializerData(this.element, this.annotation);
}
