// Generated by CoffeeScript 1.7.1
(function() {
  var ArrayFilter, Filter, Filters, createFilter, _,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  _ = require('underscore');

  Filters = (function() {
    function Filters(filters, subfilters) {
      this.filters = filters;
      this.subfilters = subfilters;
    }

    Filters.prototype.filter = function(key, val, detail, query) {
      var filterFuncs, subfilter;
      if (!this.contains(key, detail, query)) {
        return query;
      }
      if (this.filters[key]) {
        return this.filters[key].query(query, val);
      }
      filterFuncs = this.parseFilterKey(key);
      subfilter = this.subfilters[filterFuncs.subFilter];
      return subfilter.query(query.where(filterFuncs.schemaPath), val);
    };

    Filters.prototype.contains = function(key, detail, query) {
      var filterFuncs;
      if (key in this.filters) {
        return this.filters[key].canFilterRoute(detail);
      }
      if (detail) {
        return false;
      }
      filterFuncs = this.parseFilterKey(key);
      return filterFuncs.schemaPath in query.model.schema.paths && filterFuncs.subFilter in this.subfilters;
    };

    Filters.prototype.parseFilterKey = function(key) {
      var filterFuncs;
      filterFuncs = key.split("__");
      return {
        schemaPath: filterFuncs[0],
        subFilter: filterFuncs[1] || "equals"
      };
    };

    return Filters;

  })();

  Filter = (function() {
    Filter.arrayFilters = ["in"];

    Filter.validDetailFilters = ["populate"];

    Filter.createFilter = function(filterName) {
      if (__indexOf.call(this.arrayFilters, filterName) >= 0) {
        return new ArrayFilter(filterName);
      } else {
        return new Filter(filterName);
      }
    };

    Filter.coerceData = function(data) {
      if (data && data.toLowerCase && data.toLowerCase() === "true") {
        return true;
      } else {
        if (data && data.toLowerCase && data.toLowerCase() === "false") {
          return false;
        }
      }
      return data;
    };

    function Filter(key, queryHandler) {
      this.key = key;
      this.queryHandler = queryHandler != null ? queryHandler : null;
    }

    Filter.prototype.query = function(query, val) {
      val = this.prepareData(val);
      if (_.isFunction(this.queryHandler)) {
        return this.queryHandler(query, this.key, val);
      } else {
        return query[this.key](val);
      }
    };

    Filter.prototype.prepareData = function(data) {
      return this.constructor.coerceData(data);
    };

    Filter.prototype.canFilterRoute = function(detail) {
      if (!detail) {
        return true;
      }
      return this.constructor.validDetailFilters.indexOf(this.key) > -1;
    };

    return Filter;

  })();

  ArrayFilter = (function(_super) {
    __extends(ArrayFilter, _super);

    function ArrayFilter() {
      return ArrayFilter.__super__.constructor.apply(this, arguments);
    }

    ArrayFilter.prototype.prepareData = function(data) {
      return ArrayFilter.__super__.prepareData.call(this, data).split(",");
    };

    return ArrayFilter;

  })(Filter);

  createFilter = function(filters) {
    var filterMap;
    filterMap = {};
    filters.forEach(function(filterName) {
      return filterMap[filterName] = Filter.createFilter(filterName);
    });
    return filterMap;
  };

  module.exports = new Filters(createFilter(["populate", "limit", "skip", "offset", "select", "sort"]), createFilter(["equals", "gte", "gt", "lt", "lte", "ne", "regex", "in"]));

}).call(this);
