#!/usr/bin/env dart

import 'dart:io';
import 'dart:convert';
import 'package:args/args.dart';
import 'package:path/path.dart' as p;

void die(String message) {
  print(message);
  exit(1);
}

Future<Map> loadFile(String fileName, String errorMessage) async {
  var file = File(fileName);
  if (!file.existsSync()) {
    die(errorMessage);
  }
  String content = await file.readAsString();
  return jsonDecode(content);
}

void mergeFiles(String inputfilename, String mergefilename) async {
  var infile = await loadFile(inputfilename, "Requires an input file");
  var mergefile =
      await loadFile(mergefilename, "Requires a file to merge into");

  for (var entry in infile.keys) {
    if (mergefile[entry] == null || entry.substring(0, 1) == '@') {
      mergefile[entry] = infile[entry];
    }
  }

  List removeEntries = [];
  for (var entry in mergefile.keys) {
    if (infile[entry] == null && entry.substring(0, 2) != '@@') {
      removeEntries.add(entry);
    }
  }
  for (var removeEntry in removeEntries) {
    mergefile.remove(removeEntry);
  }

  await File(mergefilename)
      .writeAsString(JsonEncoder.withIndent("  ").convert(mergefile));
  print("Successfully merged strings from $inputfilename into $mergefilename");
}

void listUntranslated(String file, List<String> ignore) async {
  var infile = await loadFile(file, "Requires an input file");
  var source = {};
  var sourceFile = p.join(p.dirname(file), 'intl_messages.arb');
  if (File(sourceFile).existsSync()) {
    source = await loadFile(sourceFile, 'intl_messages loading failed');
  }

  var entries = 0;
  var translated = 0;

  for (var entry in infile.keys) {
    if (entry.substring(0, 2) == '@@') {
      continue;
    }
    entries++;
    if (entry == infile[entry] || infile[entry] == source[entry]) {
      var message = "$file: $entry";
      if (ignore.contains(entry)) {
        translated++;
      } else {
        print(message);
      }
    } else {
      translated++;
    }
  }
  print("$file: " +
      ((translated / entries) * 100).floor().toString() +
      '% translated');
}

void cliUntranslated(List<String> arguments) async {
  var parser = ArgParser();
  parser.addMultiOption('ignore');
  var result = parser.parse(arguments);
  for (var file in result.rest) {
    listUntranslated(file, result['ignore']);
  }
}

void main(List<String> arguments) async {
  exitCode = 0;

  final String usage =
      "Usage: arbtool merge intl_messages.arb file.arb\n       arbtool untranslated file.arb";

  if (arguments.isEmpty) {
    die(usage);
  }

  var action = arguments[0];

  if (action == "merge") {
    if (arguments.length != 3) {
      die("Usage: arbtool merge intl_messages.arb file.arb");
    }
    var inputfilename = arguments[1];
    var mergefilename = arguments[2];
    mergeFiles(inputfilename, mergefilename);
  } else if (action == "untranslated") {
    List<String> cliArgs = List.from(arguments);
    cliArgs.removeAt(0);
    cliUntranslated(cliArgs);
  } else {
    die(usage);
  }
}
