var fs = require("fs");


function DummyApiError(msg) {
    var self = this;

    self.toString = function () {
        return "<DummyApiError " + self.msg + ">";
    };
}


function DummyApi() {
    var self = this;

    // test hooks

    self.reset = function() {
        self.kv_store = {};
        self.config_store = {};
        self.metrics = {};
        self.http_get = {};
        self.http_post = {};
        self.outbound_sends = [];
        self.logs = [];
        self.request_calls = [];
        self.waiting_replies = [];
        self.done_calls = 0;
    };
    self.reset();

    self.add_reply = function(reply) {
        self.waiting_replies.push(reply);
    };

    self.load_http_fixture = function(filename) {
        var data = fs.readFileSync(filename);
        var fixture = JSON.parse(data);
        self.add_http_fixture(fixture);
    };

    self._http_post_key = function(url, data) {
        try {
            var json = JSON.parse(data);
            var keys = Object.keys(json).sort();
            var frags = keys.map(function (k) {
                return '"' + k + '":' + JSON.stringify(json[k]);
            });
            data = "{" + frags.join(",") + "}";
        }
        catch (e) {}
        return url + "|" + data;
    };

    self.add_http_fixture = function(fixture) {
        if (fixture.method == "POST") {
            var key = self._http_post_key(fixture.url,
                                          JSON.stringify(fixture.data));
            self.http_post[key] = JSON.stringify(fixture.body);
        }
        else {
            self.http_get[fixture.url] = JSON.stringify(fixture.body);
        }
    };

    self._dispatch_command = function(cmd, reply) {
        var handler_name = ("_handle_" +
                            cmd.cmd.replace('.', '_').replace('-', '_'));
        var handler = self[handler_name];
        if (!handler) {
            throw new DummyApiError("Unknown command " + cmd.cmd);
        }
        if (handler) {
            handler.call(self, cmd, reply);
        }
    };

    self._populate_reply = function(orig_cmd, reply) {
        reply.cmd = orig_cmd.cmd;
        return reply;
    };

    self._handle_kv_get = function(cmd, reply) {
        var value = self.kv_store[cmd.key];
        reply(self._populate_reply(cmd, {
            success: true,
            value: value
        }));
    };

    self._handle_kv_set = function(cmd, reply) {
        self.kv_store[cmd.key] = cmd.value;
        reply(self._populate_reply(cmd, {
            success: true
        }));
    };

    self._handle_config_get = function(cmd, reply) {
        var value = self.config_store[cmd.key];
        reply(self._populate_reply(cmd, {
            success: true,
            value: value
        }));
    };

    self._record_metric = function (store_name, metric_name, value, agg) {
        var store = self.metrics[store_name];
        if (typeof store == 'undefined') {
            self.metrics[store_name] = store = {};
        }
        var metric = store[metric_name];
        if (typeof metric == 'undefined') {
            store[metric_name] = metric = {'agg': agg};
        }
        if (metric.agg != agg) return false;
        metric[metric.length] = value;
        return true;
    };

    self._handle_metrics_fire = function(cmd, reply) {
        var success = self._record_metric(cmd.store, cmd.metric, cmd.value,
                                          cmd.agg);
        reply(self._populate_reply(cmd, {
            success: success
        }));
    };

    self._handle_http_method = function(method, key, cmd, reply) {
        var store = (method == "POST") ? self.http_post : self.http_get;
        var reply_data = {};
        var data = store[key];
        if (typeof data != 'undefined') {
            reply_data.success = true;
            reply_data.body = data;
            reply_data.code = 200;
        }
        else {
            reply_data.success = false;
            reply_data.reason = method + " from unknown key: " + key;
            console.log(reply_data.reason);
        }
        reply(self._populate_reply(cmd, reply_data));
    };

    self._handle_http_get = function(cmd, reply) {
        self._handle_http_method("GET", cmd.url, cmd, reply);
    };

    self._handle_http_post = function(cmd, reply) {
        var key = self._http_post_key(cmd.url, cmd.data);
        self._handle_http_method("POST", key, cmd, reply);
    };

    self._handle_outbound_reply_to = function(cmd, reply) {
         self.request_calls.push(cmd);
         reply(self.waiting_replies.shift());
    };

    self._handle_outbound_send_to_tag = function(cmd, reply) {
        self.outbound_sends.push(cmd);
        reply(self._populate_reply(cmd, {success: true}));
    };

    // original api

    self.populate_command = function(cmd_name, cmd) {
        cmd.cmd = cmd_name;
        return cmd;
    };

    self.request = function(cmd_name, cmd_data, reply) {
        var cmd = self.populate_command(cmd_name, cmd_data);
        self._dispatch_command(cmd, reply);
    };

    self.log_info = function(msg) {
        self.logs.push(msg);
    };

    self.done = function() {
        self.done_calls += 1;
    };
}

// exports
this.DummyApi = DummyApi;

@@ -2549,32 +2549,526 @@
    %7D));%0A    %7D;%0A%0A
+    self._handle_kv_incr = function(cmd, reply) %7B%0A        var orig_value = self.kv_store%5Bcmd.key%5D;%0A        orig_value = (typeof orig_value == 'undefined') ? 0 : orig_value;%0A        orig_value = Number(orig_value);%0A        var amount = cmd.amount;%0A        amount = (typeof amount == 'undefied') ? 1 : amount;%0A        self.kv_store%5Bcmd.key%5D = orig_value + amount;%0A        reply(self._populate_reply(cmd, %7B%0A            success: true,%0A            value: self.kv_store%5Bcmd.key%5D%0A        %7D));%0A    %7D;%0A%0A
     self._handle

Add support for kv.incr in dummy api.