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

// *** Creating objects ***
// Matrix objectName(fps);
Matrix matrix(25);
// Buttons objectName(firstPin, lastPin, readInterval, jumping, ducking);
Buttons buttons(2, 5, 10, false, false);
Obstacles obstacle("Alien", 30);
//Character character();

// *** 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("Player", spaceshipSprite, 8, 8, 11, 16, 10, true);
// GameObject cityBackground ("City", citySprite, 64, 14, 0, 10, 10, false);
GameObject enemy("Obstacle", enemySprite, 8, 8, 64, 16, 0, true);
GameObject raumschiff("Raumschiff", raumschiffSprite, 8, 8, 0, 10, 10, true, true);
Projectile *projectiles = (Projectile*) malloc(sizeof(Projectile) * PROJECTILE_COUNT);
GameObject city("City", citySprite, 64, 14, 0, 0, 18, true );
GameObject suburbs("Suburbs", suburbsSprite, 64, 14, 0, 0, 18, true );
GameObject nature("Nature", natureSprite, 64, 14, 0, 0, 18, true );
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(&city);
  matrix.add(&suburbs);
  matrix.add(&nature);
  matrix.add(&spaceship);
  matrix.add(&enemy);
  matrix.printRenderQueue();

  obstacle.setTimestamp(millis());
  obstacle.setCount(1);

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

void loop() {
  /*while (!choseChar) {
    matrix.drawObject();
    matrix.drawObject();
    
  }*/
  // Global system tick
  systemtime = millis();

  matrix.checkCollision(&spaceship);

  // Buttons
  buttons.update();
  buttons.moveObject(&spaceship);
 
 // Obstacles
  obstacle.moveObstacle(&enemy);
  obstacle.respawn(&enemy);
  

  // 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();

}