var bot;

var scoreboard = {};

loadKarma = function(cb) {
  bot.fsGetData('karma', 'karma.json', function(err, res) {
    if(err) {
      console.log("Error loading karma data " + err);
      scoreboard = {};
      return;
    }

    scoreboard = JSON.parse(res);

    cb && cb();
  });
}

saveKarma = function(cb) {
  bot.fsStoreData('karma', 'karma.json', JSON.stringify(scoreboard), function() {
    cb && cb();
  });
}

module.exports.init = function(b) {
  bot = b;
  loadKarma();
};

var inc = /(\w+)\+\+/;
var incfor = /(\w+)\+\+\s+(\sfor)?\s+(.+)/;
var dec = /(\w+)--/;
var decfor = /(\w+)--\s*(\sfor)?\s+(.+)/;

// Watch for messages of the following forms
// dru++
// dru++ for some reason
module.exports.message = function(text, from, to, reply, raw) {
  var re;

  scoreboard[to] = scoreboard[to] || {};

  if (re = incfor.exec(text)) {
    var user = re[1],
      reason = re[2];

    scoreboard[to][user] = scoreboard[to][user] || { points: 0, reasons: [] };
    scoreboard[to][user]['points']++;
    scoreboard[to][user]['increasons'].push(reason);

    //    reply(user + " now has " + scoreboard[user]['points'] + " points (nth place!), including 1 for " + reason); // #todo nth place
    saveKarma();
  } 
  else if (re = inc.exec(text)) {
    var user = re[1];

    scoreboard[to][user] = scoreboard[to][user] || { points: 0, reasons: [] };
    scoreboard[to][user]['points']++;

    //    reply(user + " now has " + scoreboard[user]['points'] + " points (nth place!)"); // #todo nth place
    saveKarma();
  }
  else if (re = decfor.exec(text)) {
    var user = re[1],
      reason = re[2];

    scoreboard[to][user] = scoreboard[to][user] || { points: 0, reasons: [] };
    scoreboard[to][user]['points']--;
    scoreboard[to][user]['decreasons'].push(reason);

    saveKarma();
  }
  else if (re = dec.exec(text)) {
    var user = re[1];

    scoreboard[to][user] = scoreboard[to][user] || { points: 0, reasons: [] };
    scoreboard[to][user]['points']--;

    saveKarma();
  }
};

module.exports.commands = {

  top3: function(r, parts, reply, command, from, to) { // todo: use regex parsed commands to implement topN
    var users_and_scores = [],
    rank = 1;

    scoreboard[to] = scoreboard[to] || {};

    // yolo js
    for (var user in scoreboard[to]) {
      users_and_scores.push([user, scoreboard[to][user]['points']]);
    }

    // Sort pairs by score: [["dru", 4], ["suroi", 53]]
    users_and_scores = users_and_scores.sort(function (a, b) {
      return a[1] <= b[1];
    });

    users_and_scores = users_and_scores.slice(0,3);
    var output = "";
    for (var i = 0; i < users_and_scores.length; i++) {
      output += users_and_scores[i][0] + ": " + users_and_scores[i][1] + ", ";
    }
    output = output.substring(0, output.length-2);

    reply(output);
  },

  karma: function(r, parts, reply, command, from, to) {
    var user = parts[0],
    points = 0;

    scoreboard[to] = scoreboard[to] || {};

    if (scoreboard[to][user]) {
      points = scoreboard[to][user]['points'];
    }

    reply(user + " has "  + points + " karma");
    // todo: point reasons
  }

};

@@ -488,28 +488,112 @@
 %7D;%0A%0A
-var inc = /(%5Cw+)%5C+%5C+
+// todo: these are probably wrong somehow%0Avar postinc = /(%5B%5E%5Cs%5C+-%5D+)%5C+%5C+/;%0Avar preinc = /%5C+%5C+(%5B%5E%5Cs%5C+-%5D+)
 /;%0Av
@@ -606,18 +606,24 @@
 for = /(
-%5Cw
+%5B%5E%5Cs%5C+-%5D
 +)%5C+%5C+%5Cs
@@ -649,16 +649,20 @@
 var 
+post
 dec = /(
 %5Cw+)
@@ -661,17 +661,53 @@
 = /(
-%5Cw
+%5B%5E%5Cs%5C+-%5D
 +)--/;%0A
+var predec = /--(%5B%5E%5Cs%5C+-%5D+)/;%0A
 var 
@@ -721,10 +721,16 @@
 = /(
-%5Cw
+%5B%5E%5Cs%5C+-%5D
 +)--
@@ -805,16 +805,25 @@
 / dru++%0A
+// ++dru%0A
 // dru++
@@ -839,16 +839,59 @@
  reason%0A
+// dru--%0A// --dru%0A// dru-- for some reason%0A
 module.e
@@ -1422,16 +1422,41 @@
 f (re = 
+preinc.exec(text) %7C%7C post
 inc.exec
@@ -2003,32 +2003,32 @@
 aveKarma();%0A  %7D%0A
-
   else if (re = 
@@ -2027,16 +2027,41 @@
 f (re = 
+predec.exec(text) %7C%7C post
 dec.exec

fix some regexes and add some more