// Copyright (c) 2014, 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.

/// Script to create boilerplate for a Polymer element.
/// Produces new .html entry point for a polymer app and updates the
/// pubspec.yaml to reflect it.
///
/// Run this script with pub run:
///
///     pub run polymer:new_entry <html_file>
///
library polymer.bin.new_entry;

import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart';
import 'package:source_span/source_span.dart';

void printUsage() {
  print('pub run polymer:new_entry entry_point_file.html');
}

void main(List<String> args) {
  var parser = new ArgParser(allowTrailingOptions: true);
  parser.addFlag('help', abbr: 'h');
  var entryPoint;

  try {
    var options = parser.parse(args);
    if (options['help']) {
      printUsage();
      return;
    }
    entryPoint = options.rest[0];
  } catch (e) {
    print('$e\n');
    printUsage();
    exitCode = 1;
    return;
  }

  // If the entrypoint file has no extension, add .html to it.
  if (path.extension(entryPoint) == '') {
    entryPoint = '${entryPoint}.html';
  }

  var outputDir = path.dirname(entryPoint);
  var outputDirLocation = new Directory(outputDir);

  if (!outputDirLocation.existsSync()) {
    outputDirLocation.createSync(recursive: true);
  }

  outputDir = outputDirLocation.resolveSymbolicLinksSync();
  var pubspecDir = _findDirWithFile(outputDir, 'pubspec.yaml');

  if (pubspecDir == null) {
    print('Could not find pubspec.yaml when walking up from $outputDir');
    exitCode = 1;
    return;
  }

  var relativeEntryPoint = path.relative(
      path.join(outputDir, path.basename(entryPoint)), from: pubspecDir);

  try {
    if (_createBoilerPlate(relativeEntryPoint, pubspecDir)) {
      print('Added $entryPoint to ${path.join(pubspecDir, "pubspec.yaml")}');
    }
    print('Successfully created:');
    print('  ' + path.join(pubspecDir, entryPoint));
  } catch (e, t) {
    print('Exception: $e\n$t');
    print('Error creating files in $outputDir');
    exitCode = 1;
  }

  return;
}

String _findDirWithFile(String dir, String filename) {
  while (!new File(path.join(dir, filename)).existsSync()) {
    var parentDir = path.dirname(dir);
    // If we reached root and failed to find it, bail.
    if (parentDir == dir) return null;
    dir = parentDir;
  }
  return dir;
}

// Returns true if the pubspec file was modified. It might not be modified if
// there was a monolithic polymer transformer in the pubspec, or if the entry
// point for some reason already existed in the pubspec.
bool _createBoilerPlate(String entryPoint, String pubspecDir) {
  String html = '''
<!doctype html>
<html>
  <head>
    <!-- link rel="import" href="path_to_html_import.html" -->
  </head>
  <body>
    <!-- HTML for body here -->
    <script type="application/dart">export 'package:polymer/init.dart';</script>
  </body>
</html>
''';

  new File(path.join(pubspecDir, entryPoint)).writeAsStringSync(html);

  var pubspecPath = path.join(pubspecDir, 'pubspec.yaml');
  var pubspecText = new File(pubspecPath).readAsStringSync();
  var transformers = loadYaml(pubspecText)['transformers'];
  var entryPoints;

  var insertionPoint;
  var textToInsert = '';

  if (transformers != null) {
    // If there are transformers in the pubspec, look for the polymer
    // transformers, get the entry points, and delete the old entry points.
    SourceSpan transformersSourceSpan = transformers.span;

    SourceSpan polymerTransformerSourceSpan;
    SourceSpan entryPointsSourceSpan;
    for (var e in transformers) {
      if (e == 'polymer') {
        // If they had an empty polymer transformer, just get rid of it (we will
        // replace it with our own map style one).
        var polymerRegex = new RegExp(r'\n\s*-\spolymer\s*');
        // Insert right after the newline.
        insertionPoint = pubspecText.indexOf(polymerRegex) + 1;
        pubspecText = pubspecText.replaceFirst(polymerRegex, '\n');
      } else if (e is YamlMap && e['polymer'] != null) {
        polymerTransformerSourceSpan = e['polymer'].span;

        var existing = e['polymer']['entry_points'];
        if (existing == null && e['polymer'].containsKey('entry_points')) {
          if (path.split(entryPoint)[0] != 'web') {
            print('WARNING: Did not add entry_point $entryPoint to pubspec.yaml'
                ' because of existing empty `entry_points` field in polymer'
                ' transformer. This defaults to treating all files under `web/`'
                ' as entry points, but you tried to add an entry point outside'
                ' of the `web/` folder. You will need to explicitly list all'
                ' entrypoints that you care about into your pubspec in order to'
                ' include any outside of `web/`.');
          }
          return false;
        }
        entryPoints = (existing == null
            ? []
            : (existing is String ? [existing] : existing.toList()));

        if (entryPoints.contains(entryPoint)) return false;
        entryPoints.add(entryPoint);

        if (existing != null) {
          entryPointsSourceSpan = existing.span;
        }
      }
    }

    if (polymerTransformerSourceSpan == null) {
      if (insertionPoint == null) {
        insertionPoint = transformersSourceSpan.start.offset;
      }
      textToInsert = '- polymer:\n    entry_points:\n';
    } else if (entryPointsSourceSpan == null) {
      insertionPoint = polymerTransformerSourceSpan.start.offset;
      textToInsert = '    entry_points:\n';
    } else {
      insertionPoint = entryPointsSourceSpan.start.offset;
      pubspecText = '${pubspecText.substring(0, insertionPoint)}'
          '${pubspecText.substring(entryPointsSourceSpan.end.offset)}';
    }
  } else {
    // There were no transformers at all.
    insertionPoint = pubspecText.length;
    var optionalNewline = pubspecText.endsWith('\n') ? '' : '\n';
    textToInsert = '''
${optionalNewline}transformers:
- polymer:
    entry_points:
''';
    entryPoints = [entryPoint];
  }

  if (entryPoints == null) entryPoints = [entryPoint];
  // TODO(dgrove): Once dartbug.com/20409 is addressed, use that here.
  var entryPointsText = entryPoints.map((e) => '    - $e').join('\n');

  textToInsert += entryPointsText;
  if (insertionPoint == pubspecText.length) {
    pubspecText = '${pubspecText}${textToInsert}';
  } else {
    pubspecText = '${pubspecText.substring(0, insertionPoint)}'
        '${textToInsert}\n${pubspecText.substring(insertionPoint)}';
  }

  _writePubspec(pubspecPath, pubspecText);
  return true;
}

_writePubspec(String pubspecPath, String text) {
  new File(pubspecPath).writeAsStringSync(text);
}
