import processing.core.*; 
import processing.xml.*; 

import java.applet.*; 
import java.awt.*; 
import java.awt.image.*; 
import java.awt.event.*; 
import java.io.*; 
import java.net.*; 
import java.text.*; 
import java.util.*; 
import java.util.zip.*; 
import java.util.regex.*; 

public class diana5 extends PApplet {

//
//    by Abelardo Gil-Fournier
//    originally published at The Croopier, http://www.croopier.com
//    a site where news are game-reversed.
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

// http://www.reuters.com/article/idUSTRE61H4IS20100218
// http://www.logistica.enfasis.com/notas/14901-construiran-ciudad-juarez-dos-nuevas-maquiladoras
// http://www.maquilaportal.com/news/index.php/blog/show/Two-new-maquladoras-to-be-built-in-Ciudad-Juarez.html
// http://209.85.135.132/search?q=cache:oM_giVtWG_UJ:www.newspapertree.com/news/2677-mexico-president-felipe-calderon-and-the-super-maquiladora+ciudad+juarez+apple+plant&cd=1&hl=en&ct=clnk&client=firefox-a
// http://www.laht.com/article.asp?ArticleId=352582&CategoryId=14091
// http://www.businessweek.com/news/2010-02-11/america-movil-wins-mexico-antitrust-approval-for-telmex-control.html

// http://www.latimes.com/news/nationworld/world/la-fg-mexico-narcos29-2009oct29,0,6889517.story
// http://www.musica.com/letras.asp?letra=1654778


Diana D;
Shooter S;
boolean over;
PFont fuente;
PImage esq[];

public void setup() {
  size(320,520,P2D);
  background(0);
  rectMode(CORNER);
  textMode(SCREEN);
  textAlign(CENTER);
  frameRate(60);
  smooth();    
  char[] charset = {'0','1','2','3','4','5','6','7','8','9'};
  fuente = createFont("Arial Black",100, true, charset);
  esq = new PImage[4];  
  for (int n = 0; n < 4; n++) {
    String nombre = "esq"+(n+1)+".png";
    esq[n] = loadImage(nombre);
  }    
  D = new Diana(1); 
  S = new Shooter();
  over = false;
}

public void idle() {
  if (S.vida == 0) {
    S = new Shooter();
    D = new Diana(1);
  }
  boolean continuar = false;
  for (int n = 0; n < D.Arcos.size(); n++) {
    Arco A = (Arco) D.Arcos.get(n);
    continuar = continuar || !A.destruido;
  }
  if (!continuar) {
    for (int n = 0; n < S.Bullets.size(); n++) {
      Bullet B = (Bullet) S.Bullets.get(n);
      B.active = false;
    }
    D = new Diana(D.numA+1);  
  }
  else {
    over = false;
    for (int n = 0; n < S.Bullets.size(); n++) {
      Bullet B = (Bullet) S.Bullets.get(n);    
      if (B.vy > 0 && B.active) over = true;    
    }
  }
}

public void draw() {
  if (frameCount %50 == 0) println(frameRate);
  if (!over) background(235);  
  else background(map(pow(sin(frameCount*.1f),2),0,1,255,225));  
  idle();
  D.draw();
  S.draw();
  int t = 50;
  for (int n = 0; n < 4; n++) {
    switch(n) {
      case 0:image(esq[n], 0, 0); break;
      case 1:image(esq[n], width-t, 0);break;
      case 2:image(esq[n], width-t,height-t);break;
      case 3:image(esq[n], 0,height-t);break;
    }
  }   
  
}

public void mouseReleased() {
  if (S.over && S.Bullets.size() < 6)
    S.shoot();
}


class Arco {
 
  int fcDestruido;
  boolean destruido;
  float ang0, ang;
  float dAng;
  
  Arco(float ang0_, float dAng_) {
    fcDestruido = -100;
    destruido = false;
    ang0 = ang0_;
    dAng = dAng_;
  }
  
  public void draw(Diana D, float ang_) {
    if (frameCount - fcDestruido < 20) {
      if (frameCount %10 > 5) fill(100);
      else noFill();
    }
    else if (!destruido) fill(0,150);
    else noFill();
    ang = ang_+ ang0;
    arc(D.x, D.y, 2*D.radio, 2*D.radio, ang, ang+dAng);
  }
  
}

class Bullet {
 
  int x, y;
  int l;
  int vy;
  boolean active;
  
  Bullet(Shooter S_) {
    x = S_.x;
    y = S_.y;
    l = 5;
    vy = -4;
    active = true;
  }
  
  public void idle() {  
    y += vy;             
    if (y > height || y < 0) active = false;
  }
  
  public void draw() {
    if (active) {
      idle();
      fill(0,150);
      rect(x-1, y, 2, l); 
    }
  }
  
}
class Diana {

  int x, y;
  int radio;
  int grosor;
  int numA;
  float ang;
  float dAng;
  float w;
  int[] fcDestruido;
  boolean[] destruido;
  ArrayList Arcos;
  int fcStart;
  
  Diana(int numA_) {
    numA = numA_;    
    radio = 110;
    grosor = 15;
    x = width/2;
    y = height/2-80;
    w = random(.03f,.05f)+numA*0.0025f;
    if (numA %2 == 0) w *= -1;
    dAng = 1.f;
    if (numA > 2) dAng -= dAng*.2f;    
    Arcos = new ArrayList();
    for (int n = 0; n < numA; n++) 
      Arcos.add(new Arco(n*TWO_PI/(float)(numA), 1.f));
    fcStart = frameCount;
  }
  
  public void idle() {   
    ang += w;
  }
  
  public void draw() {
    idle();
    stroke(0);
    noStroke();
    fill(250);
    ellipse(x, y, 2*radio, 2*radio);    
    for (int n = 0; n < Arcos.size(); n++) {
      Arco A = (Arco) Arcos.get(n);
      A.draw(this,ang);
    }
    fill(235);
    ellipse(x, y, 2*radio-2*grosor, 2*radio-2*grosor);
    textFont(fuente);
    if (frameCount - fcStart < 60 && frameCount%20 > 10) {
      fill(10);
      text(numA, x, y+35);
    }
  }
  
  public int estado(int x_, int stB_) {   // 0: vacio; 1: destruye; 2: rebota
    int tmp = 0;
    boolean choque = false;
    for (int n = 0; n < Arcos.size(); n++) {
      Arco A = (Arco) Arcos.get(n);
      if (!A.destruido) {
        int x0 = x + floor(D.radio*cos(A.ang));
        int x1 = x + floor(D.radio*cos(A.ang+A.dAng));
        int xMin = min(x0, x1); 
        int xMax = max(x0, x1);
        if (x_ == constrain(x_, xMin, xMax)) {
          int dy = floor(sin(A.ang+A.dAng*.5f));    
          if (dy == 0 && stB_ == 1) {
            tmp = 1; 
            A.destruido = true;
            A.fcDestruido = frameCount;
            choque = true;
            break;
          }
          if (dy < 0 && stB_ == 2) {tmp = 2; choque = true; break;}
        }
      }
    }
    if (!choque && stB_ == 2) {
      Arcos.add(new Arco(PI+HALF_PI-ang,random(.5f,1.f)));
      tmp = 3;
    }    
    return tmp;
  }
  
}
class Shooter {
  
  int x, y;
  int l;
  ArrayList Bullets;
  int fcDestruido;
  int vida;
  boolean over;
  
  Shooter() {
    x = width/2;
    y = height-130;
    l = 15;
    Bullets = new ArrayList();
    fcDestruido = -100;
    vida = 3;
    over = false;
  }
  
  public void draw() {
    idle();   
    noStroke();
    fill(105); 
    ellipse(x, y+l+10, 70, 70);
    if (over) fill(250);
    else fill(235);     
    ellipse(x, y+l+10, 60, 60);       
    fill(105);     
    if (frameCount - fcDestruido < 20 && frameCount %10 > 5) noFill();   
    triangle(x, y, x+l, y+2*l, x-l, y+2*l);    
    stroke(200);  
    for (int n = 0; n < 3; n++) {
      int tmpX = width/2-(n-1)*(l/1+1);
      int tmpY = height-95;
      if (vida-1 < n) noFill();
      triangle(tmpX, tmpY, tmpX+l*.25f, tmpY+l*.5f, tmpX-l*.25f, tmpY+l*.5f);
    }
    for (int n = 0; n < Bullets.size(); n++) {
      Bullet B = (Bullet) Bullets.get(n);
      B.draw(); 
    }
  }
  
  public void idle() {
    if (dist(mouseX, mouseY, x, y+l+10) < 35) over = true;
    else over = false;     
    for (int n = 0; n < Bullets.size(); n++) {   
      Bullet B = (Bullet) Bullets.get(n);     
      int st = 0;
      if (B.vy < 0) {
        if (B.y == constrain(B.y, D.y + D.radio - D.grosor, D.y + D.radio))
          st = D.estado(B.x, 1);              
        else if (B.y == constrain(B.y, D.y - D.radio, D.y - D.radio + D.grosor))
          st = D.estado(B.x, 2);            
      }
      else {
        if (B.y == constrain(B.y, S.y, S.y+l)) {
          fcDestruido = frameCount;
          B.active = false; 
          vida--;         
        }
      }
      if (st == 1 || st == 3) Bullets.remove(n);
      if (st == 2) B.vy *= -1;     
      if (!B.active) Bullets.remove(n);
    }
  }
  
  public void shoot() {
    Bullets.add(new Bullet(this));
  }
  
}

  static public void main(String args[]) {
    PApplet.main(new String[] { "--bgcolor=#c4c4c4", "diana5" });
  }
}
