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

/**
 * Final phase of the polymer transformation: includes any additional polyfills
 * that may needed by the deployed app.
 */
library polymer.src.build.polyfill_injector;

import 'dart:async';

import 'package:barback/barback.dart';
import 'package:html5lib/dom.dart' show Document, Node, DocumentFragment;
import 'package:html5lib/parser.dart' show parseFragment;
import 'common.dart';

/**
 * Ensures that any scripts and polyfills needed to run a polymer application
 * are included. For example, this transformer will ensure that there is a
 * script tag that loads the shadow_dom polyfill and interop.js (used for the
 * css shimming).
 *
 * This step also replaces "packages/browser/dart.js" and the Dart script tag
 * with a script tag that loads the dart2js compiled code directly.
 */
class PolyfillInjector extends Transformer with PolymerTransformer {
  final TransformOptions options;

  PolyfillInjector(this.options);

  /** Only run on entry point .html files. */
  Future<bool> isPrimary(Asset input) =>
      new Future.value(options.isHtmlEntryPoint(input.id));

  Future apply(Transform transform) {
    return readPrimaryAsHtml(transform).then((document) {
      bool shadowDomFound = false;
      bool jsInteropFound = false;
      bool customElementFound = false;
      Element dartJs;
      final dartScripts = <Element>[];

      for (var tag in document.queryAll('script')) {
        var src = tag.attributes['src'];
        if (src != null) {
          var last = src.split('/').last;
          if (last == 'interop.js') {
            jsInteropFound = true;
          } else if (_shadowDomJS.hasMatch(last)) {
            shadowDomFound = true;
          } else if (_customElementJS.hasMatch(last)) {
            customElementFound = true;
          } else if (last == 'dart.js') {
            dartJs = tag;
          }
        }

        if (tag.attributes['type'] == 'application/dart') {
          dartScripts.add(tag);
        }
      }

      if (dartScripts.isEmpty) {
        // This HTML has no Dart code, there is nothing to do here.
        transform.addOutput(transform.primaryInput);
        return;
      }

      // TODO(jmesserly): ideally we would generate an HTML that loads
      // dart2dart too. But for now dart2dart is not a supported deployment
      // target, so just inline the JS script. This has the nice side effect of
      // fixing our tests: even if content_shell supports Dart VM, we'll still
      // test the compiled JS code.
      if (options.directlyIncludeJS) {
        // If using CSP add the "precompiled" extension
        final csp = options.contentSecurityPolicy ? '.precompiled' : '';

        // Replace all other Dart script tags with JavaScript versions.
        for (var script in dartScripts) {
          final src = script.attributes['src'];
          if (src.endsWith('.dart')) {
            script.attributes.remove('type');
            script.attributes['src'] = '$src$csp.js';
          }
        }
        // Remove "packages/browser/dart.js"
        if (dartJs != null) dartJs.remove();
      } else if (dartJs == null) {
        document.body.nodes.add(parseFragment(
              '<script src="packages/browser/dart.js"></script>'));
      }

      _addScript(urlSegment) {
        document.head.nodes.insert(0, parseFragment(
              '<script src="packages/$urlSegment"></script>\n'));
      }

      // JS interop code is required for Polymer CSS shimming.
      if (!jsInteropFound) _addScript('browser/interop.js');
      if (!customElementFound) {
        _addScript('custom_element/custom-elements.debug.js');
      }

      // This polyfill needs to be the first one on the head
      // TODO(jmesserly): this is .debug to workaround issue 13046.
      if (!shadowDomFound) _addScript('shadow_dom/shadow_dom.debug.js');

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

final _shadowDomJS = new RegExp(r'shadow_dom\..*\.js', caseSensitive: false);
final _customElementJS = new RegExp(r'custom-elements\..*\.js',
    caseSensitive: false);
