/**
 * Copyright 2014
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#!/usr/bin/env node

var
  nopt          = require('nopt'),
  fs            = require('fs'),
  Path          = require('path'),
  glob          = require('glob'),
  async         = require('async'),
  MessageFormat = require('../'),
  knownOpts = {
    "locale"    : String,
    "inputdir"  : Path,
    "output"    : Path,
    "watch"     : Boolean,
    "namespace" : String,
    "include"   : String,
    "stdout"    : Boolean,
    "verbose"   : Boolean,
    "help"      : Boolean
  },
  description = {
    "locale"    : "locale(s) to use [mandatory]",
    "inputdir"  : "directory containing messageformat files to compile",
    "output"    : "output where messageformat will be compiled",
    "namespace" : "global object in the output containing the templates",
    "include"   : "glob patterns for files to include from `inputdir`",
    "stdout"    : "print the result in stdout instead of writing in a file",
    "watch"     : "watch `inputdir` for changes",
    "verbose"   : "print logs for debug"
  },
  defaults = {
    "inputdir"  : process.cwd(),
    "output"    : process.cwd(),
    "watch"     : false,
    "namespace" : 'i18n',
    "include"   : '**/*.json',
    "stdout"    : false,
    "verbose"   : false,
    "help"      : false
  },
  shortHands = {
    "l"  : "--locale",
    "i"  : "--inputdir",
    "o"  : "--output",
    "ns" : "--namespace",
    "I"  : "--include",
    "s"  : "--stdout",
    "w"  : "--watch",
    "v"  : "--verbose",
    "?"  : "--help"
  },
  options = (function() {
    var o = nopt(knownOpts, shortHands, process.argv, 2);
    for (var key in defaults) {
      o[key] = o[key] || defaults[key];
    }
    if (o.argv.remain) {
      if (o.argv.remain.length >= 1) o.inputdir = o.argv.remain[0];
      if (o.argv.remain.length >= 2) o.output = o.argv.remain[1];
    }
    if (!o.locale || o.help) {
      var usage = ['Usage: messageformat -l [locale] [OPTIONS] [INPUT_DIR] [OUTPUT_DIR]'];
      if (!o.help) {
        usage.push("Try 'messageformat --help' for more information.");
        console.error(usage.join('\n'));
        process.exit(-1);
      }
      usage.push('\nAvailable options:');
      for (var key in shortHands) {
        var desc = description[shortHands[key].toString().substr(2)];
        if (desc) usage.push('   -' + key + ',\t' + shortHands[key] + (shortHands[key].length < 8 ? '  ' : '') + '\t' + desc);
      }
      console.log(usage.join('\n'));
      process.exit(0);
    }
    if (fs.existsSync(o.output) && fs.statSync(o.output).isDirectory()) {
      o.output = Path.join(o.output, 'i18n.js');
    }
    o.namespace = o.namespace.replace(/^window\./, '')
    return o;
  })(),
  _log = (options.verbose ? function(s) { console.log(s); } : function(){});

function write(options, data) {
  data = data.join('\n');
  if (options.stdout) { _log(''); return console.log(data); }
  fs.writeFile( options.output, data, 'utf8', function(err) {
    if (err) return console.error('--->\t' + err.message);
    _log(options.output + " written.");
  });
}

function parseFileSync(options, mf, file) {
  var path = Path.join(options.inputdir, file),
      lc0 = mf.lc,
      file_parts = file.split(/[.\/]+/),
      r = '';
  if (!fs.statSync(path).isFile()) {
    _log('Skipping ' + file);
    return '';
  }
  for (var i = file_parts.length - 1; i >= 0; --i) {
    if (file_parts[i] in MessageFormat.locale) { mf.lc = file_parts[i]; break; }
  }
  try {
    var text = fs.readFileSync(path, 'utf8'),
          nm = file.replace(/\.[^.]*$/, '').replace(/\\/g, '/'),
          gn = mf.globalName + '["' + nm + '"]';
    _log('Building ' + gn + ' from `' + file + '` with locale "' + mf.lc + '"');
    r = gn + '=' + mf.precompileObject(JSON.parse(text));
  } catch (ex) {
    console.error('--->\tParse error in ' + path + ': ' + ex.message);
  } finally {
    mf.lc = lc0;
  }
  return r;
}

function build(options, callback) {
  var lc = options.locale.trim().split(/[ ,]+/),
      mf = new MessageFormat(lc[0], false, options.namespace),
      compiledMessageFormat = [];
  for (var i = 1; i < lc.length; ++i) MessageFormat.loadLocale(lc[i]);
  _log('Input dir: ' + options.inputdir);
  _log('Included locales: ' + lc.join(', '));
  glob(options.include, {cwd: options.inputdir}, function(err, files) {
    if (!err) async.each(files,
      function(file, cb) {
        var pf = parseFileSync(options, mf, file);
        if (pf) compiledMessageFormat.push(pf);
        cb();
      },
      function() {
        var data = ['(function(G){G[\'' + mf.globalName + '\']=' + mf.functions()]
          .concat(compiledMessageFormat)
          .concat('})(this);\n');
        return callback(options, data);
      }
    );
  });
}


build(options, write);

if (options.watch) {
  _log('watching for changes in ' + options.inputdir + '...\n');
  require('watchr').watch({
    path: options.inputdir,
    ignorePaths: [ options.output ],
    listener: function(changeType, filePath) { if (/\.json$/.test(filePath)) build(options, write); }
  });
}

@@ -1,8 +1,29 @@
+#!/usr/bin/env node%0A%0A
 /**%0A * C
@@ -38,17 +38,16 @@
  2014%0A *
- 
 %0A * Lice
@@ -219,17 +219,16 @@
 se at%0A *
- 
 %0A *     
@@ -272,17 +272,16 @@
 E-2.0%0A *
- 
 %0A * Unle
@@ -599,37 +599,16 @@
 e.%0A */%0A%0A
-#!/usr/bin/env node%0A%0A
 var%0A  no

move comment to make the CLI executable again