#!/usr/bin/env dart
// 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.

/**
 * A main program that takes as input a source Dart file and a number
 * of JSON files representing translations of messages from the corresponding
 * Dart file. See extract_to_json.dart and make_hardcoded_translation.dart.
 *
 * This produces a series of files named
 * "messages_<locale>.dart" containing messages for a particular locale
 * and a main import file named "messages_all.dart" which has imports all of
 * them and provides an initializeMessages function.
 */
library generate_from_json;

import 'dart:convert';
import 'dart:io';
import 'package:intl/extract_messages.dart';
import 'package:intl/src/intl_message.dart';
import 'package:intl/generate_localized.dart';
import 'package:path/path.dart' as path;
import 'package:args/args.dart';
import 'package:serialization/serialization.dart';

/**
 * Keeps track of all the messages we have processed so far, keyed by message
 * name.
 */
Map<String, MainMessage> messages;

main() {
  var targetDir;
  var args = new Options().arguments;
  var parser = new ArgParser();
  parser.addFlag("suppress-warnings", defaultsTo: false,
      callback: (x) => suppressWarnings = x);
  parser.addOption("output-dir", defaultsTo: '.',
      callback: (x) => targetDir = x);
  parser.addOption("generated-file-prefix", defaultsTo: '',
      callback: (x) => generatedFilePrefix = x);
  parser.parse(args);
  var dartFiles = args.where((x) => x.endsWith("dart")).toList();
  var jsonFiles = args.where((x) => x.endsWith(".json")).toList();
  if (dartFiles.length == 0 || jsonFiles.length == 0) {
    print('Usage: generate_from_json [--output-dir=<dir>]'
        ' [--generated-file-prefix=<prefix>] file1.dart file2.dart ...'
        ' translation1.json translation2.json ...');
    exit(0);
  }

  // We're re-parsing the original files to find the corresponding messages,
  // so if there are warnings extracting the messages, suppress them.
  suppressWarnings = true;
  var allMessages = dartFiles.map((each) => parseFile(new File(each)));

  messages = new Map();
  for (var eachMap in allMessages) {
    eachMap.forEach((key, value) => messages[key] = value);
  }
  for (var arg in jsonFiles) {
    var file = new File(arg);
    generateLocaleFile(file, targetDir);
  }

  var mainImportFile = new File(path.join(targetDir,
      '${generatedFilePrefix}messages_all.dart'));
  mainImportFile.writeAsStringSync(generateMainImportFile());
}

var s = new Serialization();
var format = const SimpleFlatFormat();
var r = s.newReader(format);

recreateIntlObjects(key, value) {
  if (value == null) return null;
  if (value is String || value is int) return Message.from(value, null);
  if (value is List) {
    var newThing = r.read(value);
    return newThing;
  }
  throw new FormatException("Invalid input data $value");
}

/**
 * Create the file of generated code for a particular locale. We read the json
 * data and create [BasicTranslatedMessage] instances from everything,
 * excluding only the special _locale attribute that we use to indicate the
 * locale.
 */
void generateLocaleFile(File file, String targetDir) {
  var src = file.readAsStringSync();
  var data = JSON.decode(src);
  data.forEach((k, v) => data[k] = recreateIntlObjects(k, v));
  var locale = data["_locale"].string;
  allLocales.add(locale);

  var translations = [];
  data.forEach((key, value) {
    if (key[0] != "_") {
      translations.add(new BasicTranslatedMessage(key, value));
    }
  });
  generateIndividualMessageFile(locale, translations, targetDir);
}

/**
 * A TranslatedMessage that just uses the name as the id and knows how to look
 * up its original message in our [messages].
 */
class BasicTranslatedMessage extends TranslatedMessage {
  BasicTranslatedMessage(String name, translated) :
      super(name, translated);

  MainMessage get originalMessage =>
      (super.originalMessage == null) ? _findOriginal() : super.originalMessage;

  // We know that our [id] is the name of the message, which is used as the
  //key in [messages].
  MainMessage _findOriginal() => originalMessage = messages[id];
}