/**
 * Instanssidemo
 * by Juho Järvinen 2010
 */

import processing.opengl.*;
import ddf.minim.*;

AudioPlayer player;
Minim minim;
int songpos; // song position in ms
int songlen; // song length in ms

// yleisiä apumuuttujia vähentämään laskutoimituksia luupeissa
int leveys2, korkeus2; // width/2, height/2

// alku
PImage akuva1, akuva2, akuva3;
PFont font;
int y, fade;
int lapsetup = 768;
int juho1 = 270;

// plasma
int pos1, pos2, pos3, pos4, tpos1, tpos2, tpos3, tpos4;
int[] aSin = new int[512];
int[] colb = new int[256];
PImage laama2pic, laama1pic, kanipic, sorsapic, riikinpic;
int laama2 = 276;
int laama1 = 283;
int kani = 184;
int sorsa = 227;
int riikinkukko = 317;

// gridi
float boxSize = 40;
float depth = 300;
color boxFill = color(0, 64, 0, 255);
int imgx;
int dx,dy;
PImage juho2pic, juho7pic;
int juho2 = 174;
int juho7 = 228;

// blendi
PImage kuva1, kuva2, kuva3, juho3pic;
float rot = 0;
float sca1 = 1.7;
float sca1min = 1.7;
float sca1max = 3.5;
float sca2 = 4.0;
float sca2min = 1.7;
float sca2max = 4.0;
int up1 = 1;
int up2 = 1;
int juho3 = 323;

// moire
PImage m, mb1;
int mkesk; // moirekuvan keskipiste
int[] mdx;
int[] mdy;
int index = 0;
float mrot = 0;
float msca1 = 1.0;
float msca1min = 0.5;
float msca1max = 1.2;
float msca2 = 1.0;
float msca2min = 0.5;
float msca2max = 2.0;
int mup1 = 1;
int mup2 = 0;
PImage juho8pic, juho4pic, juho5pic, juho7bwpic;
int juho8 = 390;
int juho4 = 237;
int juho5 = 262;
int juho7bw = 228;

// greetz
PImage varoluontopic;
int varoluonto = 280;
String[] greetings = {
  " Greetings to: ",
  " Artificial People ",
  " Cubicle ",
  " Kulta!<3 ",
  " Amiga ",
  " Sceners ",
  " Lamers ",
  " Everyone @ Instanssi ",
};
color[] greetcols = new color[8];

// loppu
int loppufeidi = 255;

/////////////////////////////////////////////////////////////////////////

void setup()
{
  size(1024, 768, OPENGL);
  //size(screen.width, screen.height, OPENGL); // HUOM! käytä tätä demossa.. EI TOIMI!!!?
  hint(DISABLE_DEPTH_TEST);
  hint(DISABLE_OPENGL_ERROR_REPORT);
//  frameRate(60);

  noCursor();
  background(0);

  leveys2 = width/2;
  korkeus2 = height/2;

  // alku
  akuva1 = loadImage("title.png");
  akuva2 = loadImage("varolapsia.png");
  akuva3 = loadImage("juho01a.png");
  font = loadFont("Impact-100.vlw");
  textFont(font);

  // HUOM! tässä kohtaa laita latauskuva näkyviin jos käytät

  // song
  minim = new Minim(this);
  player = minim.loadFile("designaalinuopio.mp3");
  songlen = player.length();

  // plasma
  for (int i = 0; i < 512; i++) {
    float rad = (i * 0.703125) * 0.0174532;
    aSin[i] = int(sin(rad) * 1024);
  }
  for (int i = 0; i < 256; i++) {
    colb[i] = int(random(256));
  }
  laama2pic = loadImage("laama2.png");
  laama1pic = loadImage("laama1.png");
  kanipic = loadImage("kani.png");
  sorsapic = loadImage("sorsa.png");
  riikinpic = loadImage("riikinkukko.png");

  // gridi (
  juho2pic = loadImage("juho02.png");
  juho7pic = loadImage("juho07.png");

  // blendi
  kuva1 = loadImage("seven-1.jpg");
  kuva2 = loadImage("seven-2.jpg");
  kuva3 = loadImage("seven-2.jpg");
  juho3pic = loadImage("juho03.png");

  // moire
  m = loadImage("m.png");
  mb1 = loadImage("mb1.png");
  juho8pic = loadImage("juho08.png");
  juho4pic = loadImage("juho04.png");
  juho5pic = loadImage("juho05.png");
  juho7bwpic = loadImage("juho07bw.png");
  mkesk = m.width/2;
  String rivit[] = loadStrings("positions-old.txt");
  if (rivit == null) {
    exit();  // HUOM! aseta joku muuttuja joka skippaa pallomoiret?
  }
  mdx = new int[rivit.length];
  mdy = new int[rivit.length];
  for (int i=0; i < rivit.length; i++) {
    String[] palat = split(rivit[i], ",");
    mdx[i] = int(palat[0]);
    mdy[i] = int(palat[1]);
  }

  // greetz
  varoluontopic = loadImage("varoluontopolku.png");
  greetcols[0] = color(0,0,0);
  greetcols[1] = color(0,255,0);
  greetcols[2] = color(0,127,127);
  greetcols[3] = color(255,0,0);
  greetcols[4] = color(127,127,127);
  greetcols[5] = color(255,0,255);
  greetcols[6] = color(0,0,255);
  greetcols[7] = color(255,127,0);

  // ladataan muistiin isot kuvat ettei nyi
  picdump();
  
  // play song
  player.play();
}

void picdump() {
  tint(0,0);
  image(m,0,0);
  image(mb1,0,0);
  image(kuva1,0,0);
  image(kuva2,0,0);
  image(kuva3,0,0);
  background(0);
}

/////////////////////////////////////////////////////////////////////////

void draw()
{
  songpos = player.position();

  pushMatrix();

  // eri partit
  if (songpos < 10000) {
    alku();
  }
  else if (songpos < 15000) {
    alku();
    varolapsia();
  }
  else if (songpos < 20000) {
    alku();
    varolapsia();
    juho1();
  }
  else if (songpos < 22000) {
    alkupois();
    lapsetpois();
    juho1pois();
  }
  else if (songpos < 30000) {
    moireLBW();
    juho8();
  }
  else if (songpos < 38000) {
    moireLBW();
    juho8pois();
    juho4();
  }
  else if (songpos < 50000) {
    moireRGB();
    juho4pois();
    juho5();
  }
  else if (songpos < 54000) {
    moireRGB();
    juho5pois();
  }
  else if (songpos < 60000) {
    blendi();
    juho3();
  }
  else if (songpos < 62000) {
    blendi();
    juho3pois();
  }
  else if (songpos < 75000) {
    fill(0,255,0,64);
    stroke(boxFill);
    gridi(1);
    noLights();
    juho7();
  }
  else if (songpos < 78000) {
    fill(0,255,0,64);
    stroke(boxFill);
    gridi(1);
    noLights();
    juho7pois();
  }
  else if (songpos < 89000) {
    stroke(255);
    gridi(2);
    noLights();
    juho2();
  }
  else if (songpos < 92000) {
    stroke(255);
    gridi(2);
    noLights();
    juho2pois();
  }
  else if (songpos < 94000) {
    greetz(0);
  }
  else if (songpos < 97000) {
    greetz(1);
  }
  else if (songpos < 99000) {
    greetz(2);
  }
  else if (songpos < 103000) {
    greetz(3);
  }
  else if (songpos < 105000) {
    greetz(4);
  }
  else if (songpos < 107000) {
    greetz(5);
  }
  else if (songpos < 109000) {
    greetz(6);
  }
  else if (songpos < 111000) {
    greetz(7);
  }
  else if (songpos < 121000) {
    greetz(7);
    varoluontopolku();
  }
  else if (songpos < 128000) {
    plasma(1);
    luontopois();
    laama2();
  }
  else if (songpos < 135000) {
    plasma(1);
    laama2();
    laama1();
  }
  else if (songpos < 143000) {
    plasma(1);
    laama2pois();
    laama1();
  }
  else if (songpos < 151000) {
    plasma(1);
    laama1pois();
    kani();
  }
  else if (songpos < 163000) {
    plasma(2);
    kanipois();
    sorsa();
  }
  else if (songpos < 176000) {
    plasma(2);
    sorsapois();
    riikinkukko();
  }
  else if (songpos < 181000) {
    plasma(2);
    riikinpois();
  }
  else if (songpos < 195000) {
    moireBW();
  }
  else if (songpos < 223000) {
    pushMatrix();
    moireBW();
    popMatrix();
    juho7bw();
  }
  else if (songpos < 251000) {
    pushMatrix();
    moireBW();
    popMatrix();
    juho7bwpois();
  }
  else if (songpos < 258300) {
    loppu();
  }
  else {
    exit();
  }

  popMatrix();

  // print song position
//  fill(0,255,0,255); // tekstin väri
//  text(songpos,10,height-32);
}

void stop()
{
  player.close();
  minim.stop();
  super.stop();
}

/////////////////////////////////////////////////////////////////////////

void alku() {
  if (fade<255) fade += 1;
  tint(fade,255);
  image(akuva1,0,0,width,height);
}
void alkupois() {
  if (fade>0) fade -= 2;
  else fade = 0;
  tint(fade,255);
  image(akuva1,0,0,width,height);
}

void varolapsia() {
  if (lapsetup>0) lapsetup -= 3;
  else lapsetup = 0;
  tint(255,255);
  image(akuva2,17,lapsetup);
}
void lapsetpois() {
  if (lapsetup<768) lapsetup += 6;
  else lapsetup = 768;
//  tint(255,255);
  image(akuva2,17,lapsetup);
}

void varoluontopolku() {
  if (varoluonto>0) varoluonto -= 3;
  else varoluonto = 0;
  tint(255,255);
  image(varoluontopic,varoluonto,0);
}
void luontopois() {
  if (varoluonto<280) varoluonto += 4;
  else varoluonto = 280;
  tint(255,255);
  image(varoluontopic,varoluonto,0);
}

void juho1() {
  if (juho1>0) juho1 -= 3;
  else juho1 = 0;
  tint(255,255);
  image(akuva3,-juho1,0);
}
void juho1pois() {
  if (juho1<270) juho1 += 4;
  else juho1 = 270;
  tint(255,255);
  image(akuva3,-juho1,0);
}

void juho8() {
  if (juho8>0) juho8 -= 3;
  else juho8 = 0;
  tint(255,255);
  image(juho8pic,-juho8,0);
}
void juho8pois() {
  if (juho8<390) juho8 += 4;
  else juho8 = 390;
  tint(255,255);
  image(juho8pic,-juho8,0);
}

void juho4() {
  if (juho4>0) juho4 -= 3;
  else juho4 = 0;
  tint(255,255);
  image(juho4pic,juho4,0);
}
void juho4pois() {
  if (juho4<237) juho4 += 4;
  else juho4 = 237;
  tint(255,255);
  image(juho4pic,juho4,0);
}

void juho5() {
  if (juho5>0) juho5 -= 3;
  else juho5 = 0;
  tint(255,255);
  image(juho5pic,-juho5,0);
}
void juho5pois() {
  if (juho5<262) juho5 += 4;
  else juho5 = 262;
  tint(255,255);
  image(juho5pic,-juho5,0);
}

void juho3() {
  if (juho3>0) juho3 -= 3;
  else juho3 = 0;
  tint(255,255);
  image(juho3pic,-juho3,0);
}
void juho3pois() {
  if (juho3<323) juho3 += 4;
  else juho3 = 323;
  tint(255,255);
  image(juho3pic,-juho3,0);
}

void juho2() {
  if (juho2>0) juho2 -= 3;
  else juho2 = 0;
  tint(255,255);
  image(juho2pic,-juho2,0);
}
void juho2pois() {
  if (juho2<174) juho2 += 4;
  else juho2 = 174;
  tint(255,255);
  image(juho2pic,-juho2,0);
}

void juho7() {
  if (juho7>0) juho7 -= 3;
  else juho7 = 0;
  tint(255,255);
  image(juho7pic,-juho7,0);
}
void juho7pois() {
  if (juho7<228) juho7 += 4;
  else juho7 = 228;
  tint(255,255);
  image(juho7pic,-juho7,0);
}

void juho7bw() {
  if (juho7bw>0) juho7bw -= 3;
  else juho7bw = 0;
  tint(255,255);
  image(juho7bwpic,-juho7bw,0);
}
void juho7bwpois() {
  if (juho7bw<228) juho7bw += 4;
  else juho7bw = 228;
  tint(255,255);
  image(juho7bwpic,-juho7bw,0);
}

void laama2() {
  if (laama2>0) laama2 -= 3;
  else laama2 = 0;
  tint(255,255);
  image(laama2pic,laama2,0);
}
void laama2pois() {
  if (laama2<276) laama2 += 4;
  else laama2 = 276;
  tint(255,255);
  image(laama2pic,laama2,0);
}

void laama1() {
  if (laama1>0) laama1 -= 3;
  else laama1 = 0;
  tint(255,255);
  image(laama1pic,-laama1,0);
}
void laama1pois() {
  if (laama1<283) laama1 += 4;
  else laama1 = 283;
  tint(255,255);
  image(laama1pic,-laama1,0);
}

void kani() {
  if (kani>0) kani -= 3;
  else kani = 0;
  tint(255,255);
  image(kanipic,kani,0);
}
void kanipois() {
  if (kani<184) kani += 4;
  else kani = 184;
  tint(255,255);
  image(kanipic,kani,0);
}

void sorsa() {
  if (sorsa>0) sorsa -= 3;
  else sorsa = 0;
  tint(255,255);
  image(sorsapic,-sorsa,0);
}
void sorsapois() {
  if (sorsa<227) sorsa += 4;
  else sorsa = 227;
  tint(255,255);
  image(sorsapic,-sorsa,0);
}

void riikinkukko() {
  if (riikinkukko>0) riikinkukko -= 3;
  else riikinkukko = 0;
  tint(255,255);
  image(riikinpic,riikinkukko,0);
}
void riikinpois() {
  if (riikinkukko<317) riikinkukko += 4;
  else riikinkukko = 317;
  tint(255,255);
  image(riikinpic,riikinkukko,0);
}

/////////////////////////////////////////////////////////////////////////

void plasma(int type_)
{
  int type = type_;
  int index;
  int x = 0;
  int pix = 0;
  tpos4 = pos4;
  tpos3 = pos3;
  loadPixels();
  for (int i = 0; i < height; ++i) {
    tpos1 = pos1 + 2;
    tpos2 = pos2 + 1;
    tpos3 &= 511;
    tpos4 &= 511;
    for (int j = 0; j < width; ++j) {
      tpos1 &= 511;
      tpos2 &= 511;
      x = aSin[tpos1] + aSin[tpos2] + aSin[tpos3] + aSin[tpos4];
      index = 128 + (x >> 4);
      if (type == 1) {
        pixels[pix] = color(x, index, colb[constrain(index,0,255)]);
      }
      else {
        pixels[pix] = color(index, x, colb[constrain(index,0,255)]);
      }
      pix++;
      tpos1 += 2;
      tpos2 += 1;
    }
    tpos4 += 2;
    tpos3 += 1;
  }
  if (type == 1) {
    pos1 += 18;
    pos3 -= 12;
  }
  else {
    pos1 -= 18;
    pos3 += 12;
  }
  updatePixels();
}

void gridi(int type_)
{
  int type = type_;
  pushMatrix();
  // tää tekee kaikesta ufoa
  pointLight(255, 255, 255, leveys2, korkeus2, depth/2);
  // Center and spin grid
  translate(leveys2, korkeus2, depth/2);
  rotateY(frameCount * 0.01);
  rotateX(frameCount * 0.02);

  // Build grid using multiple translations 
  for (float i =- depth; i <= depth; i += boxSize){
    for (float j =- depth; j <= depth; j += boxSize){
      for (float k =- depth; k <= depth; k += boxSize){
        pushMatrix();
        translate(k, j, i);
        box(boxSize);
        popMatrix();
      }
    }
  }
  popMatrix();
}

void blendi() {
  background(0);
  rot++;

  // eka kuva
  pushMatrix();
  translate(leveys2, korkeus2);
  scale(sca1);
//  rotate(rot*TWO_PI/360);
  rotate(rot*0.01745);
  translate(-leveys2, -korkeus2);
  tint(255,225);
  image(kuva1,0,0,width,height);
  popMatrix();

  // toka kuva
  pushMatrix();
  translate(leveys2, korkeus2);
  scale(sca2);
//  rotate(-rot*TWO_PI/360);
  rotate(-rot*0.01745);
  translate(-leveys2, -korkeus2);
  tint(255,127);
  image(kuva2,0,0,width,height);
  popMatrix();

  // kolmas kuva
  blend(kuva3,0,0,width,height,0,0,width,height,DIFFERENCE);

  // kuva1 pomppu
  if (up1 > 0) {
    sca1 += 0.02;
    if (sca1 > sca1max) {
      up1 = 0;
    }
  }
  else if (up1 < 1) {
    sca1 -= 0.02;
    if (sca1 < sca1min) {
      up1 = 1;
    }
  }
  // kuva2 pomppu
  if (up2 > 0) {
    sca2 += 0.03;
    if (sca2 > sca2max) {
      up2 = 0;
    }
  }
  else if (up2 < 1) {
    sca2 -= 0.03;
    if (sca2 < sca2min) {
      up2 = 1;
    }
  }
}

void moireLBW() {
  background(255);
  mrot += 0.2;

  pushMatrix();
  translate(-mkesk+leveys2,-mkesk+korkeus2);
  translate(mkesk,mkesk);
  scale(msca2);
  translate(-mkesk,-mkesk);
  tint(0,127);
  image(m,0,0);
  popMatrix();

  pushMatrix();
  translate(-mkesk+leveys2,-mkesk+korkeus2);
  translate(mkesk,mkesk);
  scale(msca1);
//  rotate(mrot*TWO_PI/360);
  rotate(mrot*0.01745);
  translate(-mkesk,-mkesk);
  tint(0,127);
  image(m,0,0);
  popMatrix();

  pushMatrix();
  translate(-mkesk+leveys2,-mkesk+korkeus2);
  translate(mkesk,mkesk);
  scale(msca1);
//  rotate(-mrot*TWO_PI/360);
  rotate(-mrot*0.01745);
  translate(-mkesk,-mkesk);
  tint(0,127);
  image(m,0,0);
  popMatrix();

  // kuva1 pomppu
  if (mup1 > 0) {
    msca1 += 0.005;
    if (msca1 > msca1max) {
      mup1 = 0;
    }
  }
  else if (mup1 < 1) {
    msca1 -= 0.005;
    if (msca1 < msca1min) {
      mup1 = 1;
    }
  }

  // kuva2 pomppu
  if (mup2 > 0) {
    msca2 += 0.005;
    if (msca2 > msca2max) {
      mup2 = 0;
    }
  }
  else if (mup2 < 1) {
    msca2 -= 0.005;
    if (msca2 < msca2min) {
      mup2 = 1;
    }
  }
}

void moireRGB() {
  background(255);
  mrot += 0.2;
  
  pushMatrix();
  translate(-mkesk+leveys2,-mkesk+korkeus2);
  translate(mkesk,mkesk);
//  scale(msca1);
//  rotate(mrot*TWO_PI/360);
  rotate(mrot*0.01745);
  translate(-mkesk,-mkesk);
  tint(255,0,0,127);
  image(m,0,0);
  popMatrix();

  pushMatrix();
  translate(-mkesk+leveys2,-mkesk+korkeus2);
  translate(mkesk,mkesk);
//  scale(msca2);
//  rotate(-mrot*TWO_PI/360);
  rotate(-mrot*0.01745);
  translate(-mkesk,-mkesk);
  tint(0,255,0,127);
  image(m,0,0);
  popMatrix();

  pushMatrix();
  translate(-mkesk+leveys2,-mkesk+korkeus2);
  translate(mkesk,mkesk);
  scale(msca2);
  translate(-mkesk,-mkesk);
  tint(0,0,255,127);
  image(m,0,0);
  popMatrix();
  
  // kuva1 pomppu
  if (mup1 > 0) {
    msca1 += 0.002;
    if (msca1 > msca1max) {
      mup1 = 0;
    }
  }
  else if (mup1 < 1) {
    msca1 -= 0.002;
    if (msca1 < msca1min) {
      mup1 = 1;
    }
  }

  // kuva2 pomppu
  if (mup2 > 0) {
    msca2 += 0.002;
    if (msca2 > msca2max) {
      mup2 = 0;
    }
  }
  else if (mup2 < 1) {
    msca2 -= 0.002;
    if (msca2 < msca2min) {
      mup2 = 1;
    }
  }
}

void moireBW() {

  background(255);

  translate(-mkesk,-mkesk);
  image(mb1,mdx[index],mdy[index]);

  translate(width,height);
  image(mb1,0-mdx[index],0-mdy[index]);

  translate(0,-height);
  image(mb1,0-mdx[index],mdy[index]);

  translate(-width,height);
  image(mb1,mdx[index],0-mdy[index]);

  index += 1;
  if (index>mdx.length) {
    index = 0;
  }
}

void greetz(int greetline_) {

  int greetline = greetline_;

  background(255);
  fill(greetcols[greetline]); // tekstin väri
  stroke(greetcols[greetline]); // viivan väri

  // the values returned by left.get() and right.get() will be between -1 and 1,
  int xdist = player.left.size()/greetings[greetline].length();
  float xloc = map(xdist, 0, player.left.size(), 0, width);
  for (int i = 0; i < greetings[greetline].length(); i++) {
    for(int j = 0; j < player.left.size()-1; j++) {
      line(j, korkeus2 + player.left.get(j)*300, j+1, korkeus2 + player.left.get(j+1)*300);
    }
    text(greetings[greetline].charAt(i), xloc*i, korkeus2 + player.left.get(xdist*i)*50);
  }

// näyttää missä kohtaa biisissä ollaan menossa (1 ms = 1/1000 of a second)
//  float x = map(songpos, 0, songlen, 0, width);
//  stroke(255, 0, 0);
//  line(x, korkeus2 - 30, x, korkeus2 + 30);
/*
  // pyörivä kuutio
  stroke(255);
  fill(0,255,0);
  pushMatrix(); // ruudun näkymä/kamera? talteen ennen ku sotketaan
  translate(leveys2, height-200, 100);
  rotateY(radians(y));
  box(100);
  y += 1;
  popMatrix(); // talletettu näkymä takas
*/
}

void loppu() {
  if (loppufeidi>0) loppufeidi -= 1;
  else loppufeidi = 0;
  tint(loppufeidi,255);
  background(loppufeidi);

  translate(-mkesk,-mkesk);
  image(mb1,mdx[index],mdy[index]);

  translate(width,height);
  image(mb1,0-mdx[index],0-mdy[index]);

  translate(0,-height);
  image(mb1,0-mdx[index],mdy[index]);

  translate(-width,height);
  image(mb1,mdx[index],0-mdy[index]);

  index += 1;
  if (index>mdx.length) {
    index = 0;
  }
}


