/* File generated by js-routes GEM_VERSION Based on Rails routes of APP_CLASS

*/

(function() {

var DeprecatedBehavior, NodeTypes, ParameterMissing, ReservedOptions, SpecialOptionsKey, Utils, defaults, root,
  hasProp = {}.hasOwnProperty,
  slice = [].slice;

root = typeof exports !== "undefined" && exports !== null ? exports : this;

ParameterMissing = function(message) {
  this.message = message;
};

ParameterMissing.prototype = new Error();

defaults = {
  prefix: PREFIX,
  default_url_options: DEFAULT_URL_OPTIONS
};

if(window.currentLang){
  defaults.default_url_options['lang'] = window.currentLang;
}

NodeTypes = NODE_TYPES;

SpecialOptionsKey = SPECIAL_OPTIONS_KEY;

DeprecatedBehavior = DEPRECATED_BEHAVIOR;

ReservedOptions = ['anchor', 'trailing_slash', 'host', 'port', 'protocol'];

Utils = {
  default_serializer: function(object, prefix) {
    var element, i, j, key, len, prop, s;
    if (prefix == null) {
      prefix = null;
    }
    if (object == null) {
      return "";
    }
    if (!prefix && !(this.get_object_type(object) === "object")) {
      throw new Error("Url parameters should be a javascript hash");
    }
    s = [];
    switch (this.get_object_type(object)) {
      case "array":
        for (i = j = 0, len = object.length; j < len; i = ++j) {
          element = object[i];
          s.push(this.default_serializer(element, prefix + "[]"));
        }
        break;
      case "object":
        for (key in object) {
          if (!hasProp.call(object, key)) continue;
          prop = object[key];
          if ((prop == null) && (prefix != null)) {
            prop = "";
          }
          if (prop != null) {
            if (prefix != null) {
              key = prefix + "[" + key + "]";
            }
            s.push(this.default_serializer(prop, key));
          }
        }
        break;
      default:
        if (object != null) {
          s.push((encodeURIComponent(prefix.toString())) + "=" + (encodeURIComponent(object.toString())));
        }
    }
    if (!s.length) {
      return "";
    }
    return s.join("&");
  },
  custom_serializer: SERIALIZER,
  serialize: function(object) {
    if ((this.custom_serializer != null) && this.get_object_type(this.custom_serializer) === "function") {
      return this.custom_serializer(object);
    } else {
      return this.default_serializer(object);
    }
  },
  clean_path: function(path) {
    var last_index;
    path = path.split("://");
    last_index = path.length - 1;
    path[last_index] = path[last_index].replace(/\/+/g, "/");
    return path.join("://");
  },
  extract_options: function(number_of_params, args) {
    var last_el, options;
    last_el = args[args.length - 1];
    if ((args.length > number_of_params && last_el === void 0) || ((last_el != null) && "object" === this.get_object_type(last_el) && !this.looks_like_serialized_model(last_el))) {
      options = args.pop() || {};
      delete options[SpecialOptionsKey];
      return options;
    } else {
      return {};
    }
  },
  looks_like_serialized_model: function(object) {
    return !object[SpecialOptionsKey] && ("id" in object || "to_param" in object);
  },
  path_identifier: function(object) {
    var property;
    if (object === 0) {
      return "0";
    }
    if (!object) {
      return "";
    }
    property = object;
    if (this.get_object_type(object) === "object") {
      if ("to_param" in object) {
        if (object.to_param == null) {
          throw new ParameterMissing("Route parameter missing: to_param");
        }
        property = object.to_param;
      } else if ("id" in object) {
        if (object.id == null) {
          throw new ParameterMissing("Route parameter missing: id");
        }
        property = object.id;
      } else {
        property = object;
      }
      if (this.get_object_type(property) === "function") {
        property = property.call(object);
      }
    }
    return property.toString();
  },
  clone: function(obj) {
    var attr, copy, key;
    if ((obj == null) || "object" !== this.get_object_type(obj)) {
      return obj;
    }
    copy = obj.constructor();
    for (key in obj) {
      if (!hasProp.call(obj, key)) continue;
      attr = obj[key];
      copy[key] = attr;
    }
    return copy;
  },
  merge: function() {
    var tap, xs;
    xs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
    tap = function(o, fn) {
      fn(o);
      return o;
    };
    if ((xs != null ? xs.length : void 0) > 0) {
      return tap({}, function(m) {
        var j, k, len, results, v, x;
        results = [];
        for (j = 0, len = xs.length; j < len; j++) {
          x = xs[j];
          results.push((function() {
            var results1;
            results1 = [];
            for (k in x) {
              v = x[k];
              results1.push(m[k] = v);
            }
            return results1;
          })());
        }
        return results;
      });
    }
  },
  normalize_options: function(parts, required_parts, default_options, actual_parameters) {
    var i, j, key, len, options, part, parts_options, result, route_parts, url_parameters, use_all_parts, value;
    options = this.extract_options(parts.length, actual_parameters);
    if (actual_parameters.length > parts.length) {
      throw new Error("Too many parameters provided for path");
    }
    use_all_parts = DeprecatedBehavior || actual_parameters.length > required_parts.length;
    parts_options = {};
    for (key in options) {
      if (!hasProp.call(options, key)) continue;
      use_all_parts = true;
      if (this.indexOf(parts, key) >= 0) {
        parts_options[key] = value;
      }
    }
    options = this.merge(defaults.default_url_options, default_options, options);
    result = {};
    url_parameters = {};
    result['url_parameters'] = url_parameters;
    for (key in options) {
      if (!hasProp.call(options, key)) continue;
      value = options[key];
      if (this.indexOf(ReservedOptions, key) >= 0) {
        result[key] = value;
      } else {
        url_parameters[key] = value;
      }
    }
    route_parts = use_all_parts ? parts : required_parts;
    i = 0;
    for (j = 0, len = route_parts.length; j < len; j++) {
      part = route_parts[j];
      if (i < actual_parameters.length) {
        if (!parts_options.hasOwnProperty(part)) {
          url_parameters[part] = actual_parameters[i];
          ++i;
        }
      }
    }
    return result;
  },
  build_route: function(parts, required_parts, default_options, route, full_url, args) {
    var options, parameters, result, url, url_params;
    args = Array.prototype.slice.call(args);
    options = this.normalize_options(parts, required_parts, default_options, args);
    parameters = options['url_parameters'];
    result = "" + (this.get_prefix()) + (this.visit(route, parameters));
    url = Utils.clean_path(result);
    if (options['trailing_slash'] === true) {
      url = url.replace(/(.*?)[\/]?$/, "$1/");
    }
    if ((url_params = this.serialize(parameters)).length) {
      url += "?" + url_params;
    }
    url += options.anchor ? "#" + options.anchor : "";
    if (full_url) {
      url = this.route_url(options) + url;
    }
    return url;
  },
  visit: function(route, parameters, optional) {
    var left, left_part, right, right_part, type, value;
    if (optional == null) {
      optional = false;
    }
    type = route[0], left = route[1], right = route[2];
    switch (type) {
      case NodeTypes.GROUP:
        return this.visit(left, parameters, true);
      case NodeTypes.STAR:
        return this.visit_globbing(left, parameters, true);
      case NodeTypes.LITERAL:
      case NodeTypes.SLASH:
      case NodeTypes.DOT:
        return left;
      case NodeTypes.CAT:
        left_part = this.visit(left, parameters, optional);
        right_part = this.visit(right, parameters, optional);
        if (optional && ((this.is_optional_node(left[0]) && !left_part) || ((this.is_optional_node(right[0])) && !right_part))) {
          return "";
        }
        return "" + left_part + right_part;
      case NodeTypes.SYMBOL:
        value = parameters[left];
        if (value != null) {
          delete parameters[left];
          return this.path_identifier(value);
        }
        if (optional) {
          return "";
        } else {
          throw new ParameterMissing("Route parameter missing: " + left);
        }
        break;
      default:
        throw new Error("Unknown Rails node type");
    }
  },
  is_optional_node: function(node) {
    return this.indexOf([NodeTypes.STAR, NodeTypes.SYMBOL, NodeTypes.CAT], node) >= 0;
  },
  build_path_spec: function(route, wildcard) {
    var left, right, type;
    if (wildcard == null) {
      wildcard = false;
    }
    type = route[0], left = route[1], right = route[2];
    switch (type) {
      case NodeTypes.GROUP:
        return "(" + (this.build_path_spec(left)) + ")";
      case NodeTypes.CAT:
        return "" + (this.build_path_spec(left)) + (this.build_path_spec(right));
      case NodeTypes.STAR:
        return this.build_path_spec(left, true);
      case NodeTypes.SYMBOL:
        if (wildcard === true) {
          return "" + (left[0] === '*' ? '' : '*') + left;
        } else {
          return ":" + left;
        }
        break;
      case NodeTypes.SLASH:
      case NodeTypes.DOT:
      case NodeTypes.LITERAL:
        return left;
      default:
        throw new Error("Unknown Rails node type");
    }
  },
  visit_globbing: function(route, parameters, optional) {
    var left, right, type, value;
    type = route[0], left = route[1], right = route[2];
    if (left.replace(/^\*/i, "") !== left) {
      route[1] = left = left.replace(/^\*/i, "");
    }
    value = parameters[left];
    if (value == null) {
      return this.visit(route, parameters, optional);
    }
    parameters[left] = (function() {
      switch (this.get_object_type(value)) {
        case "array":
          return value.join("/");
        default:
          return value;
      }
    }).call(this);
    return this.visit(route, parameters, optional);
  },
  get_prefix: function() {
    var prefix;
    prefix = defaults.prefix;
    if (prefix !== "") {
      prefix = (prefix.match("/$") ? prefix : prefix + "/");
    }
    return prefix;
  },
  route: function(parts_table, default_options, route_spec, full_url) {
    var j, len, part, parts, path_fn, ref, required, required_parts;
    required_parts = [];
    parts = [];
    for (j = 0, len = parts_table.length; j < len; j++) {
      ref = parts_table[j], part = ref[0], required = ref[1];
      parts.push(part);
      if (required) {
        required_parts.push(part);
      }
    }
    path_fn = function() {
      return Utils.build_route(parts, required_parts, default_options, route_spec, full_url, arguments);
    };
    path_fn.required_params = required_parts;
    path_fn.toString = function() {
      return Utils.build_path_spec(route_spec);
    };
    return path_fn;
  },
  route_url: function(route_defaults) {
    var hostname, port, protocol;
    if (typeof route_defaults === 'string') {
      return route_defaults;
    }
    protocol = route_defaults.protocol || Utils.current_protocol();
    hostname = route_defaults.host || window.location.hostname;
    port = route_defaults.port || (!route_defaults.host ? Utils.current_port() : void 0);
    port = port ? ":" + port : '';
    return protocol + "://" + hostname + port;
  },
  has_location: function() {
    return typeof window !== 'undefined' && typeof window.location !== 'undefined';
  },
  current_host: function() {
    if (this.has_location()) {
      return window.location.hostname;
    } else {
      return null;
    }
  },
  current_protocol: function() {
    if (this.has_location() && window.location.protocol !== '') {
      return window.location.protocol.replace(/:$/, '');
    } else {
      return 'http';
    }
  },
  current_port: function() {
    if (this.has_location() && window.location.port !== '') {
      return window.location.port;
    } else {
      return '';
    }
  },
  _classToTypeCache: null,
  _classToType: function() {
    var j, len, name, ref;
    if (this._classToTypeCache != null) {
      return this._classToTypeCache;
    }
    this._classToTypeCache = {};
    ref = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
    for (j = 0, len = ref.length; j < len; j++) {
      name = ref[j];
      this._classToTypeCache["[object " + name + "]"] = name.toLowerCase();
    }
    return this._classToTypeCache;
  },
  get_object_type: function(obj) {
    if (root.jQuery && (root.jQuery.type != null)) {
      return root.jQuery.type(obj);
    }
    if (obj == null) {
      return "" + obj;
    }
    if (typeof obj === "object" || typeof obj === "function") {
      return this._classToType()[Object.prototype.toString.call(obj)] || "object";
    } else {
      return typeof obj;
    }
  },
  indexOf: function(array, element) {
    if (Array.prototype.indexOf) {
      return array.indexOf(element);
    } else {
      return this.indexOfImplementation(array, element);
    }
  },
  indexOfImplementation: function(array, element) {
    var el, i, j, len, result;
    result = -1;
    for (i = j = 0, len = array.length; j < len; i = ++j) {
      el = array[i];
      if (el === element) {
        result = i;
      }
    }
    return result;
  },
  namespace: function(root, namespace, routes) {
    var index, j, len, part, parts;
    parts = namespace.split(".");
    if (parts.length === 0) {
      return routes;
    }
    for (index = j = 0, len = parts.length; j < len; index = ++j) {
      part = parts[index];
      if (index < parts.length - 1) {
        root = (root[part] || (root[part] = {}));
      } else {
        return root[part] = routes;
      }
    }
  },
  make: function() {
    var routes;
    routes = ROUTES;
    routes.options = defaults;
    routes.default_serializer = function(object, prefix) {
      return Utils.default_serializer(object, prefix);
    };
    return Utils.namespace(root, NAMESPACE, routes);
  }
};

if (typeof define === "function" && define.amd) {
  define([], function() {
    return Utils.make();
  });
} else {
  Utils.make();
}

}).call(this);