#include <FastLED.h>
#include "Global_Setup.h"
#include "Matrix.h"
#include "Buttons.h"
#include "Game.h"
#include "Sprites.h"

// *** Creating objects ***
// Matrix objectName(fps);
Matrix matrix(25);
// Buttons objectName(firstPin, lastPin, readInterval);
Buttons buttons(2, 5, 10);

// *** GameObjects & Projectiles ***
// GameObject objectName(name, spriteArray, width, height, xPos, yPos, collisionLayer, visibility, standalone);
// collisionLayer (0-255)                 -> Higher can collide with lower, equal can't collide
// visibility (optinal, default: false)   -> If true, object is visible and will be displayed
// standalone (optional, default: false)  -> If true, object is not part of render queue and has to be displayed manually
GameObject spaceship("Spaceship", spaceshipSprite, 8, 8, 11, 11, 10, true);
GameObject enemy("Enemy", enemySprite, 8, 8, 46, 11, 0, true);
GameObject raumschiff("Raumschiff", raumschiffSprite, 8, 8, 0, 10, 10, true, true);
Projectile *projectiles = (Projectile*) malloc(sizeof(Projectile) * PROJECTILE_COUNT);

const byte fireButtonPin = 23;
bool fireButton, fireButtonBefore;

void setup() {
  Serial.begin(115200);
  randomSeed(analogRead(A0));
  pinMode(fireButtonPin, INPUT_PULLUP);

  matrix.init();
  buttons.init();
  
  // Add objects to render queue with matrix.add(&object)
  // Remove objects from render queue with matrix.remove(&object)
  for (int i = 0; i < PROJECTILE_COUNT; i++) {
    projectiles[i] = Projectile("Projectile #" + String(i), projectileSprite, 4, 1, 0, 0, 10);
    matrix.add(&projectiles[i]);
  }
  matrix.add(&spaceship);
  matrix.add(&enemy);
  matrix.printRenderQueue();

  // Manually draw object
  //matrix.drawObject(&raumschiff);
  // Manually erase object
  //matrix.eraseObject(&raumschiff);
  // Apply leds array to matrix
  //matrix.show();
}

void loop() {
  // Global system tick
  systemtime = millis();

  // Buttons
  buttons.update();
  buttons.moveObject(&spaceship);

  // Fire logic (just an example)
  fireButton = !digitalRead(fireButtonPin);
  if (fireButton && fireButton != fireButtonBefore) {
    static byte projectileNo = 0;
    static bool wing;
    projectiles[projectileNo].setX(spaceship.getX() + 7);
    projectiles[projectileNo].setY(wing ? spaceship.getY() : spaceship.getY() + 7);
    projectiles[projectileNo].setVisible(true);
    wing = !wing;
    projectileNo++;
    projectileNo %= PROJECTILE_COUNT;    
  }
  fireButtonBefore = fireButton;

  // Update projectiles
  for (int i = 0; i < PROJECTILE_COUNT; i++) {
    projectiles[i].update(30);
  }

  // Global timed rendering with render queue
  matrix.update();
}