import processing.core.*; 
import processing.data.*; 
import processing.event.*; 
import processing.opengl.*; 

import java.util.HashMap; 
import java.util.ArrayList; 
import java.io.File; 
import java.io.BufferedReader; 
import java.io.PrintWriter; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.IOException; 

public class Floating_Image_Field extends PApplet {

// http://r-dimension.xsrv.jp/classes_j/inheritance/
// http://r-dimension.xsrv.jp/classes_j/class_method/
// http://yoppa.org/proga10/1190.html
// http://processing.org/examples/softbody.html

class SoftBody{
  // center point
  float centerX = 0;
  float centerY = 0;
  float startX = 0;
  float startY = 0;
  float destinationX = 0;
  float destinationY = 0;
  float startDistanceFromDestination = 0;
  float radius = 45, rotAngle = -90;
  float accelX, accelY;
  float springing = .0009f, damping = .98f;
  int bodyColor;
  
  //corner nodes
  int nodes = 5;
  float nodeStartX[] = new float[nodes];
  float nodeStartY[] = new float[nodes];
  float[]nodeX = new float[nodes];
  float[]nodeY = new float[nodes];
  float[]angle = new float[nodes];
  float[]frequency = new float[nodes];
  
  // soft-body dynamics
  float organicConstant = 1;
  
   SoftBody(float x, float y, float dx, float dy, float r, int col){
    //center shape in window
    centerX = x;
    centerY = y;
    startX = x;
    startY = y;
    destinationX = dx;
    destinationY = dy;
    startDistanceFromDestination = dist(startX, startY, destinationX, destinationY);
    radius = r;
    bodyColor = col;
    // iniitalize frequencies for corner nodes
    for (int i=0; i<nodes; i++){
      frequency[i] = random(5, 12);
    }
  }
  public void drawShape() {
    //  calculate node  starting locations
    float distanceFromDestination = dist(centerX, centerY, destinationX, destinationY);
    float sizeDown = distanceFromDestination/startDistanceFromDestination;
    for (int i=0; i<nodes; i++){
      nodeStartX[i] = centerX+cos(radians(rotAngle))*radius*sizeDown*sizeDown*sizeDown;
      nodeStartY[i] = centerY+sin(radians(rotAngle))*radius*sizeDown*sizeDown*sizeDown;
      rotAngle += 360.0f/nodes;
    }
  
    // draw polygon
    curveTightness(organicConstant);
    fill(bodyColor);
    beginShape();
    for (int i=0; i<nodes; i++){
      curveVertex(nodeX[i], nodeY[i]);
    }
    for (int i=0; i<nodes-1; i++){
      curveVertex(nodeX[i], nodeY[i]);
    }
    endShape(CLOSE);
  }
  public void moveShape() {
    //move center point
//A
//    float deltaX = mouseX-centerX;
//    float deltaY = mouseY-centerY;
//B
//    float deltaX = random(-200, 200);
//    float deltaY = random(-100, -10);
//DESTINATION
    float deltaX = (destinationX-centerX)*0.02f;
    float deltaY = (destinationY-centerY)*0.02f;
    // create springing effect
    deltaX *= springing;
    deltaY *= springing;
    accelX += deltaX;
    accelY += deltaY;
  
    // move predator's center
    centerX += accelX;
    centerY += accelY;
  
    // slow down springing
    accelX *= damping;
    accelY *= damping;
  
    // change curve tightness
    organicConstant = 0;//1-((abs(accelX)+abs(accelY))*.1);
  
    //move nodes
    for (int i=0; i<nodes; i++){
      nodeX[i] = nodeStartX[i]+sin(radians(angle[i]))*(accelX*2);
      nodeY[i] = nodeStartY[i]+sin(radians(angle[i]))*(accelY*2);
      angle[i]+=frequency[i];
    }
  }
  public void update(){
      drawShape();
      moveShape();
  }
  public float getCenterX(){
    return centerX;
  }
  public float getCenterY(){
    return centerY;
  }
  public float getRadius(){
    return radius;
  }
}
/* @pjs preload="data/image.jpg"; */

SoftBody s1;
SoftBody s2;
ArrayList<SoftBody> list;
PImage backGroundImage;
public void setup() {
  size(1920, 1080);
  noStroke();
  frameRate(30);
  list = new ArrayList<SoftBody>();
  for(int i=0; i<100; i++){
    list.add(new SoftBody(random(-displayWidth, 2*displayWidth), random(0, displayHeight), displayWidth/2.0f, -2000, random(7, 53), color(0, 34, 244, 200)));
  }
  //s2 = new SoftBody(500, displayHeight-100, 25, color(255, 127, 255, 127));
  backGroundImage = loadImage("data/image.jpg");
}

public void draw() {
  //fade background
  //fill(0, 255);
  //rect(0,0,width, height);
  background(backGroundImage);  
  for(int i =0; i<list.size(); i++){
    list.get(i).update();
  }
  //s1.update();
//  s2.update();
  inOrOut(list);
//  println(list.size());

}

public void inOrOut(ArrayList<SoftBody> listSoftBody){
  for (int i=0; i<listSoftBody.size(); i++){
    if(listSoftBody.get(i).getCenterY()+listSoftBody.get(i).getRadius() < 0){
      listSoftBody.remove(i);
      list.add(new SoftBody(random(-displayWidth, 2*displayWidth), displayHeight+random(38, 50), displayWidth/2.0f, -2000, random(7, 53), color(0, 34, 244, 200)));
    }
  }
}

  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "Floating_Image_Field" };
    if (passedArgs != null) {
      PApplet.main(concat(appletArgs, passedArgs));
    } else {
      PApplet.main(appletArgs);
    }
  }
}
