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

import 'dart:convert';
import 'dart:io' as io;

import '../lib/shared_messages.dart';

const String jsonPath = '../lib/generated/shared_messages.json';
const String dart2jsPath =
    '../../compiler/lib/src/diagnostics/generated/shared_messages.dart';
const String analyzerPath =
    '../../analyzer/lib/src/generated/generated/shared_messages.dart';

final String dontEditWarning = """
/*
DON'T EDIT. GENERATED. DON'T EDIT.
This file has been generated by 'publish.dart' in the dart_messages package.

Messages are maintained in `lib/shared_messages.dart` of that same package.
After any change to that file, run `bin/publish.dart` to generate a new version
of the json, dart2js and analyzer representations.
*/""";

const String copyrightHeader = '''
// 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.''';

void markAsReadonly(String path) {
  // TODO(15078): mark as read-only. Currently not possible:
  // http://dartbug.com/15078.
}

void emitJson() {
  var input = MESSAGES;
  var outPath = io.Platform.script.resolve(jsonPath).toFilePath();
  print("Emitting JSON:");
  print("  Input: ${input.length} entries");
  print("  Output: $outPath");
  new io.File(outPath).writeAsStringSync(messagesAsJson);
  print("Emitting JSON done.");
}

/// Escapes the given string [str].
///
/// The parameter [str] may be `null` in which case the result is "null".
String escapeString(String str) {
  return JSON.encode(str);
}

/// Emits the messages in dart2js format.
///
/// The dart2js-format consists of two entities:
///   1. the `MessageKind` enum, and
///   2. the MessageKind-to-Template map `TEMPLATES`.
///
/// The template is an instance of MessageTemplate:
///
///     const MessageTemplate(
///        this.kind,
///        this.template,
///        {this.howToFix,
///         this.examples,
///         this.options: const <String>[]});
///
/// A sample output thus looks as follows:
///
///     enum MessageKind {
///       EXAMPLE_MESSAGE,
///     }
///
///     const Map<MessageKind, MessageTemplate> {
///       EXAMPLE_MESSAGE: const MessageTemplate(
///         EXAMPLE_MESSAGE,
///         "Don't use #foo with #bar",
///         howToFix: "Just don't do it",
///         options: const ['--some-flag']),
///         examples: const ['''
///     some example with bad code;'''],
///     };
void emitDart2js() {
  var input = MESSAGES;
  var outPath = io.Platform.script.resolve(dart2jsPath).toFilePath();
  print("Emitting dart2js:");
  print("  Input: ${input.length} entries");
  print("  Output: $outPath");

  StringBuffer out = new StringBuffer();
  out.writeln(copyrightHeader);
  out.writeln(dontEditWarning);
  out.writeln("import '../messages.dart' show MessageKind, MessageTemplate;");
  out.writeln();
  out.writeln("const Map<MessageKind, MessageTemplate> TEMPLATES = "
      "const <MessageKind, MessageTemplate>{ ");
  input.forEach((name, message) {
    if (!message.usedBy.contains(Platform.dart2js)) return;

    out.writeln("  MessageKind.$name: const MessageTemplate(");
    // TODO(floitsch): include id.
    out.writeln("    MessageKind.$name,");
    out.write("    ");
    out.write(escapeString(message.template));
    if (message.howToFix != null) {
      out.write(",\n    howToFix: ${escapeString(message.howToFix)}");
    }
    if (message.options != null) {
      out.write(",\n    options: const [");
      out.write(message.options.map(escapeString).join(","));
      out.writeln("]");
    }
    if (message.examples != null) {
      out.writeln(",\n    examples: const [");

      String escapeExampleContent(String content) {
        if (content.contains("\n") || content.contains('"')) {
          return 'r"""\n$content"""';
        } else if (content.contains("\\")) {
          return 'r"$content"';
        }
        return '"$content"';
      }
      for (var example in message.examples) {
        if (example is String) {
          out.write("      ");
          out.write(escapeExampleContent(example));
        } else if (example is Map) {
          out.writeln("      const {");
          example.forEach((String fileName, String content) {
            out.writeln("      '$fileName': ");
            out.write(escapeExampleContent(content));
            out.writeln(",");
          });
          out.write("      }");
        }
        out.writeln(",");
      }
      out.writeln("    ]");
    }
    out.writeln("  ),  // Generated. Don't edit.");
  });
  out.writeln("};");

  new io.File(outPath).writeAsStringSync(out.toString());
  print("Emitting dart2js done.");
}

String convertToAnalyzerTemplate(String template, holeOrder) {
  var holeMap;
  if (holeOrder != null) {
    holeMap = {};
    for (int i = 0; i < holeOrder.length; i++) {
      holeMap[holeOrder[i]] = i;
    }
  }
  int seenHoles = 0;
  return template.replaceAllMapped(new RegExp(r"#\w+|#{\w+}"), (Match match) {
    if (holeMap != null) {
      String matchedString = match[0];
      String holeName = matchedString.startsWith("#{")
          ? matchedString.substring(2, matchedString.length - 1)
          : matchedString.substring(1);
      int index = holeMap[holeName];
      if (index == null) {
        throw "Couldn't find hole-position for $holeName $holeMap";
      }
      return "{$index}";
    } else {
      return "{${seenHoles++}}";
    }
  });
}

/// Emits the messages in analyzer format.
///
/// Messages are encoded as instances of `ErrorCode` classes where the
/// corresponding class is given by the `category` field of the Message.
///
/// All instances are stored as top-level const variables.
///
/// A sample output looks as follows:
///
///     const FooCategoryErrorCode EXAMPLE_MESSAGE = const FooCategoryErrorCode(
///         "EXAMPLE_MESSAGE",
///         "Don't use {0} with {1}",
///         "Just don't do it");
void emitAnalyzer() {
  var input = MESSAGES;
  var outPath = io.Platform.script.resolve(analyzerPath).toFilePath();
  print("Emitting analyzer:");
  print("  Input: ${input.length} entries");
  print("  Output: $outPath");

  StringBuffer out = new StringBuffer();
  out.writeln(copyrightHeader);
  out.writeln(dontEditWarning);
  out.writeln("import 'package:analyzer/src/generated/error.dart';");
  out.writeln("import 'package:analyzer/src/generated/parser.dart' "
      "show ParserErrorCode;");
  input.forEach((name, message) {
    if (!message.usedBy.contains(Platform.analyzer)) return;

    Category category = message.category;
    String className = category.name + "Code";
    out.writeln();
    out.writeln("const $className $name = const $className(");
    out.writeln("    '$name',");

    String template = message.template;
    List holeOrder = message.templateHoleOrder;
    String analyzerTemplate = convertToAnalyzerTemplate(template, holeOrder);
    out.write("    ");
    out.write(escapeString(analyzerTemplate));
    out.write(",\n    ");
    out.write(escapeString(message.howToFix));
    out.writeln(");  // Generated. Don't edit.");
  });

  new io.File(outPath).writeAsStringSync(out.toString());
  print("Emitting analyzer done.");
}

/// Translates the shared messages in `../lib/shared_messages.dart` to JSON,
/// dart2js, and analyzer formats.
///
/// Emits the json-output to [jsonPath], the dart2js-output to [dart2jsPath],
/// and the analyzer-output to [analyzerPath].
void main() {
  emitJson();
  emitDart2js();
  emitAnalyzer();
}
