var caching = function (args) {
    args = args || {};
    var self = {};
    if (typeof args.store === 'object') {
        self.store = args.store;
    } else if (typeof args.store === 'string' && args.store.match(/\//)) {
        self.store = require(args.store).create(args);
    } else {
        var store_name = args.store || 'memory';
        self.store = require('./stores/' + store_name).create(args);
    }

    /**
     * Wraps a function in cache. I.e., the first time the function is run,
     * its results are stored in cache so subsequent calls retrieve from cache
     * instead of calling the function.
     *
     * @example
     *
     *   var key = 'user_' + user_id;
     *   cache.wrap(key, function(cb) {
     *       User.get(user_id, cb);
     *   }, function(err, user) {
     *       console.log(user);
     *   });
     */
    self.wrap = function (key, work, cb) {
        self.store.get(key, function (err, result) {
            if (err) { return cb(err); }
            if (result) {
                return cb(null, result);
            }

            work(function () {
                var work_args = Array.prototype.slice.call(arguments, 0);
                self.store.set(key, work_args[1], function (err) {
                    if (err) { return cb(err); }
                    cb.apply(null, work_args);
                });
            });
        });
    };

    self.get = self.store.get;

    self.set = self.store.set;

    self.del = self.store.del;

    return self;
};

module.exports = caching;