#include "Joystick.h"
#include <Arduino.h>

Joystick::Joystick(bool debug) {
  _debug = debug;
  _num_buttons = 0;
  _num_axes = 0;

  for (uint8_t i=0; i < JOYSTICK_NUM_AXES; i++) {
    _joyReport.axis[i] = 0;
  }
  for (uint8_t i=0; i < JOYSTICK_NUM_BYTES; i++) {
    _joyReport.button[i] = 0;
  }
}

void Joystick::Init() {
  Serial.begin(115200);
  delay(100);

  if (_debug) Serial.println("DEBUG: Joystick library initialized.");
}

void Joystick::AddButton(uint8_t pin, ButtonType type) {
  _buttons[_num_buttons].pin = pin;
  _buttons[_num_buttons].type = type;
  _buttons[_num_buttons].last_state = digitalRead(pin);
  _num_buttons++;
}

void Joystick::AddAxis(uint8_t pin) {
  _axes[_num_axes] = pin;
  _num_axes++;
}

void Joystick::Update() {
  JoyReport oldReport = _joyReport;
  
  for (int i = 0; i < _num_buttons; i++) {
    uint8_t value = digitalRead(_buttons[i].pin);
    // TODO: handle button according to ButtonType
  }

  for (int i = 0; i < _num_axes; i++) {
    uint16_t value = analogRead(_axes[i]);
    // TODO: convert raw analog value to something sensible for
    //   HID Analog data.
  }

  if (_joyReport != oldReport) {
    Serial.write(_joyReport);
  }
}

void Joystick::SetAxis(uint8_t axis, int16_t value) {
  if (axis >= JOYSTICK_NUM_AXES) return;
  _joyReport.axis[axis] = value;
  if (_debug) Serial.println("DEBUG: Axis change recorded.");
}

void Joystick::PressButton(uint8_t button) {
  if (button >= JOYSTICK_NUM_BUTTONS) return;
  uint8_t byte = button / 8;
  uint8_t bit = button % 8;
  _joyReport.button[byte] |= 1 << bit;
  if (_debug) Serial.println("DEBUG: Button press recorded.");
}

void Joystick::ReleaseButton(uint8_t button) {
  if (button >= JOYSTICK_NUM_BUTTONS) return;
  uint8_t byte = button / 8;
  uint8_t bit = button % 8;
  _joyReport.button[byte] |= 0 << bit;
  if (_debug) Serial.println("DEBUG: Button release recorded.");
}

void Joystick::ReleaseAllButtons() {
  for (uint8_t i = 0; i < JOYSTICK_NUM_BYTES; i++) {
    _joyReport.button[i] = 0;
  }
  if (_debug) Serial.println("DEBUG: All-button release recorded.");
}

void Joystick::Write() {
  Serial.write((uint8_t *)&_joyReport, sizeof(JoyReport));
  delay(250);
}