var MockFirmata = require("./mock-firmata"),
  sinon = require("sinon"),
  pins = require("./mock-pins"),
  five = require("../lib/johnny-five.js"),
  events = require("events"),
  Board = five.Board,
  Button = five.Button,
  board = new five.Board({
    debug: false,
    repl: false,
    io: new MockFirmata()
  });

exports["Button, Digital Pin"] = {
  setUp: function(done) {
    this.digitalRead = sinon.spy(board.io, "digitalRead");
    this.button = new Button({
      pin: 8,
      board: board
    });

    this.proto = [];

    this.instance = [{
      name: "isPullup"
    }, {
      name: "invert"
    }, {
      name: "downValue"
    }, {
      name: "upValue"
    }, {
      name: "holdtime"
    }, {
      name: "isDown"
    }];

    done();
  },

  tearDown: function(done) {
    this.digitalRead.restore();
    done();
  },

  shape: function(test) {
    test.expect(this.proto.length + this.instance.length);

    this.proto.forEach(function(method) {
      test.equal(typeof this.button[method.name], "function");
    }, this);

    this.instance.forEach(function(property) {
      test.notEqual(typeof this.button[property.name], "undefined");
    }, this);

    test.done();
  },

  down: function(test) {

    var callback = this.digitalRead.args[0][1];
    test.expect(1);

    //fake timers dont play nice with __.debounce
    this.button.on("down", function() {

      test.ok(true);
      test.done();
    });

    callback(this.button.downValue);
  },

  up: function(test) {

    var callback = this.digitalRead.args[0][1];
    test.expect(1);

    //fake timers dont play nice with __.debounce
    this.button.on("up", function() {

      test.ok(true);
      test.done();
    });
    callback(this.button.downValue);
    callback(this.button.upValue);
  },

  release: function(test) {

    var callback = this.digitalRead.args[0][1];
    test.expect(1);

    //fake timers dont play nice with __.debounce
    this.button.on("release", function() {

      test.ok(true);
      test.done();
    });
    callback(this.button.downValue);
    callback(this.button.upValue);
  }

};

exports["Button, Analog Pin"] = {
  setUp: function(done) {
    this.digitalRead = sinon.spy(board.io, "digitalRead");
    this.button = new Button({
      pin: "A0",
      board: board
    });

    this.proto = [];

    this.instance = [{
      name: "isPullup"
    }, {
      name: "invert"
    }, {
      name: "downValue"
    }, {
      name: "upValue"
    }, {
      name: "holdtime"
    }, {
      name: "isDown"
    }];

    done();
  },

  tearDown: function(done) {
    this.digitalRead.restore();
    done();
  },
  pinTranslation: function(test) {
    test.expect(1);
    test.equal(this.button.pin, 14);
    test.done();
  },
  down: function(test) {

    var callback = this.digitalRead.args[0][1];
    test.expect(1);

    //fake timers dont play nice with __.debounce
    this.button.on("down", function() {

      test.ok(true);
      test.done();
    });

    callback(this.button.downValue);
  },

  up: function(test) {

    var callback = this.digitalRead.args[0][1];
    test.expect(1);

    //fake timers dont play nice with __.debounce
    this.button.on("up", function() {
      test.ok(true);
      test.done();
    });
    callback(this.button.downValue);
    callback(this.button.upValue);
  },

  release: function(test) {

    var callback = this.digitalRead.args[0][1];
    test.expect(1);

    //fake timers dont play nice with __.debounce
    this.button.on("release", function() {

      test.ok(true);
      test.done();
    });
    callback(this.button.downValue);
    callback(this.button.upValue);
  }

};

@@ -1776,39 +1776,36 @@
 Value);%0A  %7D,%0A%0A  
-release
+hold
 : function(test)
@@ -1799,32 +1799,70 @@
 unction(test) %7B%0A
+    var clock = sinon.useFakeTimers();
 %0A    var callbac
@@ -1977,39 +1977,36 @@
 this.button.on(%22
-release
+hold
 %22, function() %7B%0A
@@ -1997,33 +1997,32 @@
 %22, function() %7B%0A
-%0A
       test.ok(tr
@@ -2018,32 +2018,55 @@
  test.ok(true);%0A
+      clock.restore();%0A
       test.done(
@@ -2105,32 +2105,53 @@
 ton.downValue);%0A
+    clock.tick(500);%0A
     callback(thi
@@ -2168,25 +2168,25 @@
 pValue);%0A  %7D
-%0A
+,
 %0A%7D;%0A%0Aexports
@@ -3403,23 +3403,20 @@
   %7D,%0A%0A  
-release
+hold
 : functi
@@ -3418,32 +3418,70 @@
 unction(test) %7B%0A
+    var clock = sinon.useFakeTimers();
 %0A    var callbac
@@ -3608,15 +3608,12 @@
 on(%22
-release
+hold
 %22, f
@@ -3616,33 +3616,32 @@
 %22, function() %7B%0A
-%0A
       test.ok(tr
@@ -3637,32 +3637,55 @@
  test.ok(true);%0A
+      clock.restore();%0A
       test.done(
@@ -3724,32 +3724,53 @@
 ton.downValue);%0A
+    clock.tick(500);%0A
     callback(thi
@@ -3791,13 +3791,13 @@
 ue);%0A  %7D
-%0A
+,
 %0A%7D;%0A

add hold tests, remove release tests (dups)