// 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 web_components.build.import_crawler;

import 'dart:async';
import 'dart:collection' show LinkedHashMap;
import 'package:code_transformers/assets.dart';
import 'package:code_transformers/messages/build_logger.dart';
import 'package:barback/barback.dart';
import 'package:html/dom.dart' show Document, Element;
import 'common.dart';
import 'messages.dart';

/// Information about an html import found in a document.
class ImportData {
  /// The [AssetId] where the html import appeared.
  final AssetId fromId;

  /// The [Document] where the html import appeared.
  final Document document;

  /// The html import element itself.
  final Element element;

  ImportData(this.document, this.element, {this.fromId});
}

/// A crawler for html imports.
class ImportCrawler {
  // Can be either an AggregateTransform or Transform.
  final _transform;
  final BuildLogger _logger;
  final AssetId _primaryInputId;

  // Optional parsed document for the primary id if available.
  final Document _primaryDocument;

  ImportCrawler(this._transform, this._primaryInputId, this._logger,
      {Document primaryDocument})
      : _primaryDocument = primaryDocument;

  /// Returns a post-ordered map of [AssetId]'s to [ImportData]. The [AssetId]'s
  /// represent an asset which was discovered via an html import, and the
  /// [ImportData] represents the [Document] where it was discovered and the
  /// html import [Element] itself.
  Future<LinkedHashMap<AssetId, ImportData>> crawlImports() {
    var documents = new LinkedHashMap<AssetId, ImportData>();
    var seen = new Set<AssetId>();

    Future doCrawl(AssetId assetId,
        {Element import, Document document, AssetId from}) {
      if (seen.contains(assetId)) return null;
      seen.add(assetId);

      Future crawlImports(Document document) {
        var imports = document.querySelectorAll('link[rel="import"]');
        var done = Future.forEach(imports,
            (i) => doCrawl(_importId(assetId, i), import: i, from: assetId));

        // Add this document after its dependencies.
        return done.then((_) {
          documents[assetId] = new ImportData(document, import, fromId: from);
        });
      }

      if (document != null) {
        return crawlImports(document);
      } else {
        return _transform.readInputAsString(assetId).then((html) {
          return crawlImports(parseHtml(html, assetId.path));
        }).catchError((error) {
          var span;
          if (import != null) span = import.sourceSpan;
          _logger.error(inlineImportFail.create({'error': error}), span: span);
        });
      }
    }

    return doCrawl(_primaryInputId, document: _primaryDocument)
        .then((_) => documents);
  }

  AssetId _importId(AssetId source, Element import) {
    var url = import.attributes['href'];
    return uriToAssetId(source, url, _transform.logger, import.sourceSpan);
  }
}
