var five = require('johnny-five');
var servocontrol = require('./servocontrol');

// To jest sekwencja naciskanych klawiszy.
// Każdy element tabeli musi odpowiadać elementowi w obiekcie KEYS.
var SEQUENCE = ["w", "i", "t", "a", "j", "s", "w", "i", "e", "c", "i", "e"];

// To jest prędkość wyrażona w stopniach na milisekundę,
// z jaką będzie obracał się serwomotor.
// Na początek najlepsza jest wartość 0,05.
var SERVO_RATE = 0.05;

// To jest opóźnienie pomiędzy okresami ruchu.
// Opóźnienie umożliwia ustabilizowanie się wszystkich elementów i zapobiega przeciążeniu ramienia.
var STEP_SETTLE_TIME = 250;

// To jest podstawowa konfiguracja serwomotoru.
// Każda para klawisz-wartość określa nazwę i konfigurację serwomotoru.
// Pole pin  określa końcówkę w złączu Arduino,
// a defaultPosition pozycję, którą przyjmuje serwomotor po uruchomieniu aplikacji.
var SERVO_CONFIG = {
  servos: {
    shoulder: {
      pin: 3,
      startPosition: 90,
    },
    elbow: {
      pin: 6,
      startPosition: 60,
    },
    wrist: {
      pin: 5,
      startPosition: 30,
      invert: true
    }
  },
  rate: SERVO_RATE,
  settleTime: STEP_SETTLE_TIME
};

// Tu wymienione są klawisze i pozycje, jakie każdy z serwomotorów musi przyjąć, aby został "naciśnięty" dany klawisz.
var KEYS = {
  a: { shoulder: 125, elbow: 19, wrist: 87 },
  b: { shoulder: 88, elbow: 21, wrist: 62 },
  c: { shoulder: 105, elbow: 21, wrist: 65 },
  d: { shoulder: 114, elbow: 21, wrist: 77 },
  e: { shoulder: 114, elbow: 19, wrist: 87 },
  f: { shoulder: 107, elbow: 21, wrist: 74 },
  g: { shoulder: 100, elbow: 21, wrist: 72 },
  h: { shoulder: 92, elbow: 21, wrist: 70 },
  i: { shoulder: 81, elbow: 20, wrist: 79 },
  j: { shoulder: 84, elbow: 21, wrist: 70 },
  k: { shoulder: 77, elbow: 21, wrist: 71 },
  l: { shoulder: 69, elbow: 21, wrist: 73 },
  m: { shoulder: 70, elbow: 21, wrist: 65 },
  n: { shoulder: 78, elbow: 21, wrist: 63 },
  o: { shoulder: 75, elbow: 20, wrist: 81 },
  p: { shoulder: 68, elbow: 20, wrist: 83 },
  q: { shoulder: 124, elbow: 16, wrist: 98 },
  r: { shoulder: 108, elbow: 20, wrist: 83 },
  s: { shoulder: 120, elbow: 20, wrist: 82 },
  t: { shoulder: 102, elbow: 20, wrist: 81 },
  u: { shoulder: 88, elbow: 21, wrist: 78 },
  v: { shoulder: 97, elbow: 21, wrist: 63 },
  w: { shoulder: 119, elbow: 18, wrist: 92 },
  x: { shoulder: 113, elbow: 21, wrist: 68 },
  y: { shoulder: 95, elbow: 20, wrist: 79 },
  z: { shoulder: 120, elbow: 21, wrist: 72 }
};

function run() {

  // Definicje stanów
  var STATE_IDLE = 0;
  var STATE_MOVING = 1;
  var STATE_PRESSING = 2;
  var STATE_RELEASING = 3;

  // Informacje o maszynie stanów
  var sequencePosition = -1;
  var state = STATE_IDLE;
  var key;

  function tick() {
    switch(state) {

      case STATE_IDLE:

        // Odczytanie następnego klawisza
        sequencePosition++;
        key = KEYS[SEQUENCE[sequencePosition]];
        if (!key) {
          process.exit();
        }
        console.log('Naciśnięty klawisz ' + SEQUENCE[sequencePosition]);

        // Przemieszczenie ramienia nad klawisz
        state = STATE_MOVING;
        servocontrol.move({
          'shoulder': key.shoulder,
          'elbow': key.elbow + 10,
          'wrist': key.wrist - 5
        }, tick);
        break;

      // Naciśnięcie klawisza.
      case STATE_MOVING:
        state = STATE_PRESSING;
        servocontrol.move({
          'elbow': key.elbow,
          'wrist': key.wrist
        }, tick);
        break;

      // Zwolnienie klawisza.
      case STATE_PRESSING:
        state = STATE_RELEASING;
        servocontrol.move({
          elbow: key.elbow + 10,
          wrist: key.wrist - 5
        }, tick);
        break;

      // Przejście do stanu jałowego i zgłoszenie zdarzenia
      case STATE_RELEASING:
        state = STATE_IDLE;
        tick();
        break;
    }
  }

  // Uruchomienie pętli obsługującej zdarzenia
  tick();
}

// Inicjalizacja sprzętu
var board = new five.Board();
board.on('ready', function() {
  servocontrol.init(board, SERVO_CONFIG, run);
});
