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

import 'dart:async';
import 'dart:collection' show LinkedHashMap;
import 'package:barback/barback.dart';
import 'package:code_transformers/assets.dart';
import 'package:code_transformers/messages/build_logger.dart';
import 'package:html/dom.dart';
import 'package:html/dom_parsing.dart' show TreeVisitor;
import 'package:path/path.dart' as path;
import 'package:source_span/source_span.dart';
import 'common.dart';
import 'import_crawler.dart';
import 'messages.dart';

/// Transformer which inlines all html imports found from the entry points. This
/// deletes all dart scripts found during the inlining, so the
/// [ScriptCompactorTransformer] should be ran first if there are any dart files
/// in html imports.
class ImportInlinerTransformer extends Transformer {
  final List<String> entryPoints;
  final List<String> bindingStartDelimiters;

  ImportInlinerTransformer(
      [this.entryPoints, this.bindingStartDelimiters = const []]);

  bool isPrimary(AssetId id) {
    if (entryPoints != null) return entryPoints.contains(id.path);
    // If no entry point is supplied, then any html file under web/ or test/ is
    // an entry point.
    return (id.path.startsWith('web/') || id.path.startsWith('test/')) &&
        id.path.endsWith('.html');
  }

  apply(Transform transform) {
    var logger = new BuildLogger(transform, convertErrorsToWarnings: true);
    return new ImportInliner(transform, transform.primaryInput.id, logger,
        bindingStartDelimiters: bindingStartDelimiters).run();
  }
}

/// Helper class which actually does all the inlining of html imports for a
/// single entry point.
class ImportInliner {
  // Can be an AggregateTransform or Transform
  final transform;
  // The primary input to start from.
  final AssetId primaryInput;
  // The logger to use.
  final BuildLogger logger;
  // The start delimiters for template bindings, such as '{{' or '[['.
  final List<String> bindingStartDelimiters;

  ImportInliner(this.transform, this.primaryInput, this.logger,
      {this.bindingStartDelimiters: const []});

  Future run() {
    var crawler = new ImportCrawler(transform, primaryInput, logger);
    return crawler.crawlImports().then((imports) {
      var primaryDocument = imports[primaryInput].document;

      // Normalize urls in the entry point.
      var changed = new _UrlNormalizer(
              primaryInput, primaryInput, logger, bindingStartDelimiters)
          .visit(primaryDocument);

      // Inline things if needed, always have at least one (the entry point).
      if (imports.length > 1) {
        _inlineImports(primaryDocument, imports);
      } else if (!changed &&
          primaryDocument.querySelectorAll('link[rel="import"]').where(
                  (import) => import.attributes['type'] != 'css').length ==
              0) {
        // If there were no url changes and no imports, then we are done.
        return;
      }

      primaryDocument
          .querySelectorAll('link[rel="import"]')
          .where((import) => import.attributes['type'] != 'css')
          .forEach((element) => element.remove());

      transform.addOutput(
          new Asset.fromString(primaryInput, primaryDocument.outerHtml));
    });
  }

  void _inlineImports(
      Document primaryDocument, LinkedHashMap<AssetId, ImportData> imports) {
    // Add a hidden div at the top of the body, this is where we will inline
    // all the imports.
    var importWrapper = new Element.tag('div')..attributes['hidden'] = '';
    var firstElement = primaryDocument.body.firstChild;
    if (firstElement != null) {
      primaryDocument.body.insertBefore(importWrapper, firstElement);
    } else {
      primaryDocument.body.append(importWrapper);
    }

    // Move all scripts/stylesheets/imports into the wrapper to maintain
    // ordering.
    _moveHeadToWrapper(primaryDocument, importWrapper);

    // Add all the other imports!
    imports.forEach((AssetId asset, ImportData data) {
      if (asset == primaryInput) return;
      var document = data.document;
      // Remove all dart script tags.
      document
          .querySelectorAll('script[type="$dartType"]')
          .forEach((script) => script.remove());
      // Normalize urls in attributes and inline css.
      new _UrlNormalizer(data.fromId, asset, logger, bindingStartDelimiters)
          .visit(document);
      // Replace the import with its contents by appending the nodes
      // immediately before the import one at a time, and then removing the
      // import from the document.
      var element = data.element;
      var parent = element.parent;
      document.head.nodes
          .toList(growable: false)
          .forEach((child) => parent.insertBefore(child, element));
      document.body.nodes
          .toList(growable: false)
          .forEach((child) => parent.insertBefore(child, element));
      element.remove();
    });
  }
}

/// To preserve the order of scripts with respect to inlined
/// link rel=import, we move both of those into the body before we do any
/// inlining. We do not start doing this until the first import is found
/// however, as some scripts do need to be ran in the head to work
/// properly (webcomponents.js for instance).
///
/// Note: we do this for stylesheets as well to preserve ordering with
/// respect to eachother, because stylesheets can be pulled in transitively
/// from imports.
void _moveHeadToWrapper(Document doc, Element wrapper) {
  var foundImport = false;
  for (var node in doc.head.nodes.toList(growable: false)) {
    if (node is! Element) continue;
    var tag = node.localName;
    var type = node.attributes['type'];
    var rel = node.attributes['rel'];
    if (tag == 'link' && rel == 'import') foundImport = true;
    if (!foundImport) continue;
    if (tag == 'style' ||
        tag == 'script' &&
            (type == null || type == jsType || type == dartType) ||
        tag == 'link' && (rel == 'stylesheet' || rel == 'import')) {
      // Move the node into the wrapper, where its contents will be placed.
      // This wrapper is a hidden div to prevent inlined html from causing a
      // FOUC.
      wrapper.append(node);
    }
  }
}

/// Internally adjusts urls in the html that we are about to inline.
// TODO(jakemac): Everything from here down is almost an exact copy from the
// polymer package. We should consolidate this logic by either removing it
// completely from polymer or exposing it publicly here and using that in
// polymer.
class _UrlNormalizer extends TreeVisitor {
  /// [AssetId] for the main entry point.
  final AssetId primaryInput;

  /// Asset where the original content (and original url) was found.
  final AssetId sourceId;

  /// Counter used to ensure that every library name we inject is unique.
  int _count = 0;

  /// Path to the top level folder relative to the transform primaryInput.
  /// This should just be some arbitrary # of ../'s.
  final String topLevelPath;

  /// Whether or not the normalizer has changed something in the tree.
  bool changed = false;

  // The start delimiters for template bindings, such as '{{' or '[['. If these
  // are found before the first `/` in a url, then the url will not be
  // normalized.
  final List<String> bindingStartDelimiters;

  final BuildLogger logger;

  _UrlNormalizer(AssetId primaryInput, this.sourceId, this.logger,
      this.bindingStartDelimiters)
      : primaryInput = primaryInput,
        topLevelPath = '../' * (path.url.split(primaryInput.path).length - 2);

  bool visit(Node node) {
    super.visit(node);
    return changed;
  }

  visitElement(Element node) {
    // TODO(jakemac): Support custom elements that extend html elements which
    // have url-like attributes. This probably means keeping a list of which
    // html elements support each url-like attribute.
    if (!isCustomTagName(node.localName)) {
      node.attributes.forEach((name, value) {
        if (_urlAttributes.contains(name)) {
          node.attributes[name] = _newUrl(value, node.sourceSpan);
          changed = value != node.attributes[name];
        }
      });
    }
    if (node.localName == 'style') {
      node.text = visitCss(node.text);
    } else if (node.localName == 'script' &&
        node.attributes['type'] == dartType &&
        !node.attributes.containsKey('src')) {
      changed = true;
    }
    return super.visitElement(node);
  }

  static final _url = new RegExp(r'url\(([^)]*)\)', multiLine: true);
  static final _quote = new RegExp('["\']', multiLine: true);

  /// Visit the CSS text and replace any relative URLs so we can inline it.
  // Ported from:
  // https://github.com/Polymer/vulcanize/blob/c14f63696797cda18dc3d372b78aa3378acc691f/lib/vulcan.js#L149
  // TODO(jmesserly): use csslib here instead? Parsing with RegEx is sadness.
  // Maybe it's reliable enough for finding URLs in CSS? I'm not sure.
  String visitCss(String cssText) {
    var url = spanUrlFor(sourceId, primaryInput, logger);
    var src = new SourceFile(cssText, url: url);
    return cssText.replaceAllMapped(_url, (match) {
      changed = true;
      // Extract the URL, without any surrounding quotes.
      var span = src.span(match.start, match.end);
      var href = match[1].replaceAll(_quote, '');
      href = _newUrl(href, span);
      return 'url($href)';
    });
  }

  String _newUrl(String href, SourceSpan span) {
    // We only want to parse the part of the href leading up to the first
    // folder, anything after that is not informative.
    var hrefToParse;
    var firstFolder = href.indexOf('/');
    if (firstFolder == -1) {
      hrefToParse = href;
    } else if (firstFolder == 0) {
      return href;
    } else {
      // Special case packages and assets urls.
      if (href.contains('packages/')) {
        var suffix = href.substring(href.indexOf('packages/') + 9);
        return '${topLevelPath}packages/$suffix';
      } else if (href.contains('assets/')) {
        var suffix = href.substring(href.indexOf('assets/') + 7);
        return '${topLevelPath}packages/$suffix';
      }

      hrefToParse = '${href.substring(0, firstFolder + 1)}';
    }

    // If we found a binding before the first `/`, then just return the original
    // href, we can't determine anything about it.
    if (bindingStartDelimiters.any((d) => hrefToParse.contains(d))) return href;

    Uri uri;
    // Various template systems introduce invalid characters to uris which would
    // be typically replaced at runtime. Parse errors are assumed to be caused
    // by this, and we just return the original href in that case.
    try {
      uri = Uri.parse(hrefToParse);
    } catch (e) {
      return href;
    }
    if (uri.isAbsolute) return href;
    if (uri.scheme.isNotEmpty) return href;
    if (uri.host.isNotEmpty) return href;
    if (uri.path.isEmpty) return href; // Implies standalone ? or # in URI.
    if (path.isAbsolute(hrefToParse)) return href;

    var id = uriToAssetId(sourceId, hrefToParse, logger, span);
    if (id == null) return href;

    // Build the new path, placing back any suffixes that we stripped earlier.
    var prefix =
        (firstFolder == -1) ? id.path : id.path.substring(0, id.path.length);
    var suffix = (firstFolder == -1) ? '' : href.substring(firstFolder);
    var newPath = '$prefix$suffix';

    if (newPath.startsWith('lib/')) {
      return '${topLevelPath}packages/${id.package}/${newPath.substring(4)}';
    }

    if (newPath.startsWith('asset/')) {
      return '${topLevelPath}assets/${id.package}/${newPath.substring(6)}';
    }

    if (primaryInput.package != id.package) {
      // Technically we shouldn't get there
      logger.error(internalErrorDontKnowHowToImport
              .create({'target': id, 'source': primaryInput, 'extra': ''}),
          span: span);
      return href;
    }

    var builder = path.url;
    return builder.normalize(builder.relative(builder.join('/', newPath),
        from: builder.join('/', builder.dirname(primaryInput.path))));
  }
}

/// Returns true if this is a valid custom element name. See:
/// <http://w3c.github.io/webcomponents/spec/custom/#dfn-custom-element-type>
bool isCustomTagName(String name) {
  if (name == null || !name.contains('-')) return false;
  return !invalidTagNames.containsKey(name);
}

/// These names have meaning in SVG or MathML, so they aren't allowed as custom
/// tags. See [isCustomTagName].
const invalidTagNames = const {
  'annotation-xml': '',
  'color-profile': '',
  'font-face': '',
  'font-face-src': '',
  'font-face-uri': '',
  'font-face-format': '',
  'font-face-name': '',
  'missing-glyph': '',
};

/// HTML attributes that expect a URL value.
/// <http://dev.w3.org/html5/spec/section-index.html#attributes-1>
///
/// Every one of these attributes is a URL in every context where it is used in
/// the DOM. The comments show every DOM element where an attribute can be used.
///
/// The _* version of each attribute is also supported, see http://goo.gl/5av8cU
const _urlAttributes = const [
  'action',
  '_action', // in form
  'background',
  '_background', // in body
  'cite',
  '_cite', // in blockquote, del, ins, q
  'data',
  '_data', // in object
  'formaction',
  '_formaction', // in button, input
  'href',
  '_href', // in a, area, link, base, command
  'icon',
  '_icon', // in command
  'manifest',
  '_manifest', // in html
  'poster',
  '_poster', // in video
  'src',
  '_src', // in audio, embed, iframe, img, input, script, source, track,video
];
