var TWO_YEARS = 2 * 365 * 24 * 60 * 60 * 1000;
var PIVOTAL_TOKEN_COOKIE = 'pivotalToken';

var pivotal = require('pivotal');
var redis = require("redis"), client = redis.createClient();
var _ = require('underscore');

exports.index = function (req, res) {
  res.render('index');
};

exports.hasToken = function (req, res, next) {
  if (req.cookies[PIVOTAL_TOKEN_COOKIE]) {
    pivotal.useToken(req.cookies[PIVOTAL_TOKEN_COOKIE]);
    res.cookie(PIVOTAL_TOKEN_COOKIE, req.cookies[PIVOTAL_TOKEN_COOKIE], { maxAge: TWO_YEARS });
    next();
  } else {
    res.set('Content-Type', 'text/javascript');
    res.send('TT.UI.requestToken();');
  }
};

exports.useToken = function (req, res) {
  res.cookie(PIVOTAL_TOKEN_COOKIE, req.body[PIVOTAL_TOKEN_COOKIE], { maxAge: TWO_YEARS });
  res.set('Content-Type', 'text/javascript');
  res.send('TT.Ajax.end();');
};

exports.getProjects = function (req, res) {
  var projectsKey = pivotal.token + '_projects';
  var projects = null;

  var callback = function (results) {
    res.set('Content-Type', 'text/javascript');
    res.send('TT.API.setProjects(' + results + ');');
  };

  client.get(projectsKey, function (err, results) {
    if (_.isEmpty(results)) {
      pivotal.getProjects(function (err, results) {
        resultsAsJson = JSON.stringify(results);

        client.set(projectsKey, resultsAsJson);
        callback(resultsAsJson); 
      });
    } else {
      callback(results);
    };
  });
};

exports.getIterations = function (req, res) {
  var iterationsKey = pivotal.token + '_project_' + req.query.project + '_iterations';

  var callback = function (results) {
    res.set('Content-Type', 'text/javascript');
    res.send(results ? 'TT.API.addIterations(' + results + ');' : '');
  }

  client.get(iterationsKey, function (err, results) {
    if (_.isEmpty(results)) {
      pivotal.getCurrentBacklogIterations(req.query.project, function (err, results) {
        resultsAsJson = JSON.stringify(results);

        client.set(iterationsKey, resultsAsJson);
        callback(resultsAsJson); 
      });
    } else {
      callback(results);
    };

  });
};

exports.getStories = function (req, res) {
  var storiesKey = pivotal.token + '_project_' + req.query.project + '_stories';

  var callback = function (results) {
    res.set('Content-Type', 'text/javascript');
    res.send(results ? 'TT.API.addStories(' + results + ');' : '');
  }

  client.get(storiesKey, function (err, results) {
    if (_.isEmpty(results)) {
      pivotal.getStories(req.query.project, { limit: 500 }, function (err, results) {
        resultsAsJson = JSON.stringify(results);

        client.set(storiesKey, resultsAsJson);
        callback(resultsAsJson); 
      });
    } else {
      callback(results);
    };

  });
};

exports.updateStory = function (req, res) {
  pivotal.updateStory(req.query.project_id, req.query.story_id, req.query.data, function (err, results) {
    res.set('Content-Type', 'text/javascript');
    res.send('TT.Ajax.end();');
  });
};

@@ -40,16 +40,44 @@
 * 1000;%0A
+var ONE_MINUTE = 1000 * 60;%0A
 var PIVO
@@ -1757,33 +1757,34 @@
  ');' : '');%0A  %7D
+;
 %0A
-
 %0A  client.get(it
@@ -1826,37 +1826,231 @@
 ) %7B%0A    
-if (_.isEmpty(results
+var parsed_results = JSON.parse(results);%0A    var timestamp = _.isObject(parsed_results) ? parsed_results.timestamp : null;%0A%0A    if (_.isEmpty(results) %7C%7C !timestamp %7C%7C timestamp %3C (new Date().getTime() - ONE_MINUTE
 )) %7B%0A   
@@ -2125,32 +2125,82 @@
 err, results) %7B%0A
+        results.timestamp = new Date().getTime();%0A
         resultsA
@@ -2665,16 +2665,17 @@
 '');%0A  %7D
+;
 %0A%0A  clie

Add timestamp to redis lookups