(function(){

var interpolatePattern = /%\{([^}]+)\}/g;

//Replace %{foo} with obj.foo
function interpolate(str, obj){
  return str.replace(interpolatePattern, function(){
    return typeof obj[arguments[1]] == 'undefined' ? arguments[0] : obj[arguments[1]];
  });
};

//Split "foo.bar" to ["foo", "bar"] if key is a string
function keyToArray(key){
  if (!key) return [];
  if (typeof key != "string") return key;
  return key.split('.');
};

function locale(){
  return I18n.locale || I18n.defaultLocale;
};

function getLocaleFromCookie(){
  var cookies = document.cookie.split(/\s*;\s*/),
      i, pair, locale;
  for (i = 0; i < cookies.length; i++) {
    pair = cookies[i].split('=');
    if (pair[0] === 'locale') { locale = pair[1]; break; }
  }
  return locale;
};

I18n.init = function(){
  this.locale = getLocaleFromCookie();
};

//Works mostly the same as the Ruby equivalent, except there are
//no symbols in JavaScript, so keys are always strings. The only time
//this makes a difference is when differentiating between keys and values
//in the defaultValue option. Strings starting with ":" will be considered
//to be keys and used for lookup, while other strings are returned as-is.
I18n.translate = function(key, opts){
  if (typeof key != "string") { //Bulk lookup
    var a = [], i;
    for (i=0; i<key.length; i++) {
      a.push(this.translate(key[i], opts));
    }
    return a;
  } else {
    opts = opts || {};
    opts.defaultValue = opts.defaultValue || null;
    key = keyToArray(opts.scope).concat(keyToArray(key));
    var value = this.lookup(key, opts.defaultValue);
    if (typeof value != "string" && value) value = this.pluralize(value, opts.count);
    if (typeof value == "string") value = interpolate(value, opts);
    return value;
  }
};

I18n.t = I18n.translate;

//Looks up a translation using an array of strings where the last
//is the key and any string before that define the scope. The current
//locale is always prepended and does not need to be provided. The second
//parameter is an array of strings used as defaults if the key can not be
//found. If a key starts with ":" it is used as a key for lookup.
//This method does not perform pluralization or interpolation.
I18n.lookup = function(keys, defaults){
  var i = 0, value = this.translations[locale()];
  defaults = typeof defaults == "string" ? [defaults] : (defaults || []);
  while (keys[i]) {
    value = value && value[keys[i]];
    i++;
  }
  if (value){
    return value;
  } else {
    if (defaults.length == 0) {
      return null;
    } else if (defaults[0].substr(0,1) == ':') {
      return this.lookup(keys.slice(0,keys.length-1).concat(keyToArray(defaults[0].substr(1))), defaults.slice(1));
    } else {
      return defaults[0];
    }
  }
};

I18n.pluralize = function(value, count){
  if (typeof count != 'number') return value;
  return count == 1 ? value.one : value.other;
};

})();

I18n.init();