// Generated by CoffeeScript 1.7.1
(function() {
  var Resource, Route, app, exports, filters, handlers, mongooseApiQuery, _,
    __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; };

  _ = require('underscore');

  mongooseApiQuery = require('mongoose-api-query');

  handlers = require('./handlers');

  app = require('./app');

  filters = require('./filters');

  Route = require('./route');

  Resource = (function() {
    Resource.ALL_ROUTES = {
      "list": Route.makeRoute('', 'get', handlers.list, false),
      "detail": Route.makeRoute('', 'get', handlers.detail, true),
      "update": Route.makeRoute('', 'put', handlers.update, true),
      "create": Route.makeRoute('', 'post', handlers.create, false),
      "destroy": Route.makeRoute('', 'delete', handlers.destroy, true)
    };

    Resource.ALL_METHODS = ['get', 'put', 'post', 'delete'];

    function Resource(resourceName, Model) {
      this.resourceName = resourceName;
      this.Model = Model;
      this.preprocessor = handlers.preprocess(this.Model);
      this.routes = [];
    }

    Resource.prototype.withRoutes = function(newRoutes) {
      var routes, validRoutes;
      if (this.addedRoutes) {
        throw new Error("Cannot register built in routes more than once");
      }
      newRoutes = this.arrayify(newRoutes);
      validRoutes = Object.keys(Resource.ALL_ROUTES);
      routes = _.map(newRoutes, (function(_this) {
        return function(routeName) {
          if (__indexOf.call(validRoutes, routeName) < 0) {
            throw new Error(("'" + routeName + "' not recognized as built in route. ") + ("Valid choices are [" + validRoutes + "]"));
          }
          return Resource.ALL_ROUTES[routeName];
        };
      })(this));
      routes.forEach(_.bind(this.insertRoute, this));
      this.addedRoutes = true;
      return this;
    };

    Resource.prototype.arrayify = function(maybeNotArray) {
      if (_.isArray(maybeNotArray)) {
        return maybeNotArray;
      } else {
        return [maybeNotArray];
      }
    };

    Resource.prototype.route = function(path, methods, detail, fn) {
      var _ref;
      if (arguments.length === 2) {
        fn = methods;
        methods = ['get'];
        detail = false;
      } else if (arguments.length === 3) {
        _ref = [false, detail], detail = _ref[0], fn = _ref[1];
      }
      if (!_.isArray(methods)) {
        methods = [methods];
      }
      methods.forEach((function(_this) {
        return function(method) {
          var route;
          route = Route.makeRoute(path, method, {
            handle: fn
          }, detail);
          return route = _this.insertRoute(route);
        };
      })(this));
      return this;
    };

    Resource.addMiddleware = function(beforeOrAfter) {
      return function(path, methods, detail, fn) {
        methods = this.arrayify(methods);
        methods.forEach((function(_this) {
          return function(method) {
            var existingRoute;
            existingRoute = _this.findRoute(path, method, detail);
            if (!existingRoute) {
              throw new Error(("Trying to add " + beforeOrAfter + " middleware on an ") + ("unregistered route (" + path + "," + method + ",isDetail=" + detail + ")"));
            }
            return existingRoute[beforeOrAfter](fn);
          };
        })(this));
        return this;
      };
    };

    Resource.prototype.before = Resource.addMiddleware('before');

    Resource.prototype.after = Resource.addMiddleware('after');

    Resource.prototype.findRoute = function(path, method, detail) {
      if ((path != null ? path.length : void 0) > 0 && path.charAt(0) !== '/') {
        path = "/" + path;
      }
      return _.findWhere(this.routes, {
        path: path,
        method: method,
        detail: detail
      });
    };

    Resource.prototype.insertRoute = function(route) {
      var existingRoute;
      existingRoute = this.findRoute(route.path, route.method, route.detail);
      if (!existingRoute) {
        return this.routes.push(route);
      } else {
        throw new Error("Trying to register route twice. " + ("" + existingRoute + " already registered. " + route + " ignored"));
      }
    };

    Resource.prototype.register = function() {
      if (!this.addedRoutes) {
        this.withRoutes('list', 'detail');
      }
      return this.routes.forEach(_.bind(this.registerRoute, this));
    };

    Resource.prototype.registerRoute = function(route) {
      var url;
      if (!route.handler) {
        return;
      }
      url = "/" + this.resourceName + (route.url());
      return app[route.method](url, this.preprocessor, this.makeHandler(route));
    };

    Resource.prototype.makeHandler = function(route) {
      return route.handlers();
    };

    Resource.prototype.filter = function(req) {
      var detail, params, query;
      detail = req.params.id != null;
      params = _.extend(req.body, req.query);
      query = this.Model.apiQuery(params);
      if (detail) {
        query = query.findOne({
          id: req.params.id
        });
      }
      return query;
    };

    Resource.prototype.setRemoveOptions = function(removeOptions) {
      this.removeOptions = removeOptions;
      return this;
    };

    Resource.prototype.setUpdateOptions = function(updateOptions) {
      this.updateOptions = updateOptions;
      return this;
    };

    return Resource;

  })();

  exports = module.exports = Resource;

}).call(this);
