import processing.serial.*;

Serial myPort;

PImage bg;

ArrayList<Plant> plants;

//images for four species
PImage bluebonnet;
PImage paintbrush;
PImage thistle;
PImage coreopsis;

// sensor values
int sensor1 = 0;
int sensor2 = 0;
int sensor3 = 0;
int sensor4 = 0;

// spawn timing
int lastSpawn1 = 0;
int lastSpawn2 = 0;
int lastSpawn3 = 0;
int lastSpawn4 = 0;

int spawnInterval = 10;   // milliseconds between spawns
//int maxPlants = 1000;   // reset limit


void setup(){
  size(1470, 890);
  bg = loadImage("final-prairie-background.png");
  
  plants = new ArrayList<Plant>();
  
  bluebonnet = loadImage("bluebonnet-glow-sm.png");
  paintbrush = loadImage("paintbrush-glow-sm.png");
  thistle = loadImage("thistle-glow-sm.png");
  coreopsis = loadImage("coreopsis-glow-stem-sm.png");
  

//bring back when connected to sensors
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[3], 9600);
  myPort.bufferUntil('\n');
}


void draw() {
  background(0);

  image(bg,0,0);

  
  handleSpawning();
  
  for (Plant p : plants) {
    p.display();
  }
  
  // remove dead plants
  for (int i = plants.size() - 1; i >= 0; i--) {
    if (plants.get(i).isDead()) {
      plants.remove(i);
    }
  }
}


void serialEvent(Serial myPort) {
  String val = myPort.readStringUntil('\n');
  
  if (val != null) {
    val = trim(val);
    String[] values = split(val, ',');
   
    if (values.length ==4) {
      sensor1 = int(values[0]);
      sensor2 = int(values[1]);
      sensor3 = int(values[2]);
      sensor4 = int(values[3]);
    }
  }
}

// sensor to spawn behaviours (change values based on serial data + wiring) maybe diff #s guide different interactions?
void handleSpawning() {
  
  //Sensor 1 (A0)
  if (sensor1 > 630 && sensor1 < 900) {
    if (millis() - lastSpawn1 > spawnInterval) {
      spawnPlant(paintbrush, sensor1);
      lastSpawn1 = millis();
    }
  }
  
  // Sensor 2 (A1)
  if (sensor2 > 680 && sensor2 < 800) {
    if (millis() - lastSpawn2 > spawnInterval) {
      spawnPlant(thistle, sensor2);
      lastSpawn2 = millis();
    }
  }
  
  // Sensor 3 (A2)
  if (sensor3 > 500 && sensor3 < 800) {
    if (millis() - lastSpawn3 > spawnInterval) {
      spawnPlant(bluebonnet, sensor3);
      lastSpawn3 = millis();
    }
  }
  
  // Sensor 4 (A3)
  if (sensor4 > 300 && sensor4 < 600) {
    if (millis() - lastSpawn4 > spawnInterval) {
      spawnPlant(coreopsis, sensor4);
      lastSpawn4 = millis();
    }
  }
}

void spawnPlant(PImage img, int sensorValue) {
  
  float x = random(width);
  float y = random(height/2, height);
  
  float opacity = map(sensorValue, 300, 800, 100, 255);
  opacity = constrain(opacity, 50, 255);
  
  plants.add(new Plant(x, y, img, opacity));
}

///-------------------
///Plant class
///-------------------

class Plant {
  
  float x;
  float y;
  PImage img;
  float opacity;
  
  float birthTime;   // when this plant was spawned
  int lifetime = 20000; // how long (ms) the plant stays visible
  
  Plant(float x_, float y_, PImage img_, float opacity_) {
    x = x_;
    y = y_;
    img = img_;
    opacity = opacity_;
    birthTime = millis();  // record the exact moment this plant was spawned
  }

  void display() {
    float age = millis() - birthTime;
    float currentOpacity = opacity * (1 - age/lifetime);
    currentOpacity = constrain(currentOpacity, 0, opacity);
    
    if (currentOpacity > 0){
      tint(255, opacity);
      image(img, x - img.width/2, y - img.height/2);
      noTint();
    }
  }
  
    boolean isDead() {
    return millis() - birthTime > lifetime;
  }
}
