import java.util.ArrayList;
import processing.core.PApplet;
import processing.core.PVector;

// Particles + Forces
// Daniel Shiffman <http://www.shiffman.net>

// A class to describe a group of Particles
// An ArrayList is used to manage the list of Particles 
// Functions are added to apply forces to all particles
// and all particles interact with Repeller objects

public class ParticleSystem {
  PApplet parent;
  ArrayList<Particle> particles;    // An arraylist for all the particles
  PVector origin;        // An origin point for where particles are birthed
  int color;

  ParticleSystem(PApplet _p, int num, PVector v, int _c) {
    parent = _p;
    particles = new ArrayList<Particle>();              // Initialize the arraylist
    origin = v.get();       // Store the origin point
    color = _c;
    for (int i = 0; i < num; i++) {
      particles.add(new Particle(parent, origin, _c));    // Add "num" amount of particles to the arraylist
    }
  }

  // A function to apply a force to all Particles
  void applyForce(PVector f) {
    for (int i = 0; i < particles.size(); i++) {
      Particle p = (Particle) particles.get(i);
      p.applyForce(f);
    }
  }

  // A function for particles to interact with all Repellers
  void applyRepellers(ArrayList<Repeller> repellers) {
    // For every Particle
    for (int i = 0; i < particles.size(); i++) {
      Particle p = (Particle) particles.get(i);
      // For every Repeller
      for (int j = 0; j < repellers.size(); j++) {
        Repeller r = (Repeller) repellers.get(j);
        // Calculate and apply a force from Repeller to Particle
        PVector repel = r.pushParticle(p);        
        p.applyForce(repel);
      }
    }
  }
  
  // A function for particles to interact with all Attractors
  void applyAttractors(ArrayList<Attractor> attractors) {
    // For every Particle
    for (int i = 0; i < particles.size(); i++) {
      Particle p = (Particle) particles.get(i);
      // For every Attractor
      for (int j = 0; j < attractors.size(); j++) {
        Attractor a = (Attractor) attractors.get(j);
        // Calculate a force exerted by "attractor" on "thing"
        PVector f = a.calcGravForce(p);
        // Apply that force to the thing
        p.applyForce(f);
      }
    }
  }
  
  void applyAttractor(Attractor _a) {
    // For every Particle
    for (int i = 0; i < particles.size(); i++) {
      Particle p = (Particle) particles.get(i);

      // Calculate a force exerted by "attractor" on "thing"
      PVector f = _a.calcGravForce(p);
      // Apply that force to the thing
      p.applyForce(f);

    }
  }

  void run() {
    // Cycle through the ArrayList backwards b/c we are deleting
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle p = (Particle) particles.get(i);
      p.run();
      if (p.dead()) {
        particles.remove(i);
      }
    }
  }
  
  

  void addParticle() {
    particles.add(new Particle(parent, origin,color));
  }

  void addParticle(Particle p) {
    particles.add(p);
  }

  // A method to test if the particle system still has particles
  boolean dead() {
    if (particles.isEmpty()) {
      return true;
    } 
    else {
      return false;
    }
  }

}



