/*
 * Main.java
 *
 * Created on 29 décembre 2004, 16:14
 */

package hyperion;

import java.applet.*;
import java.awt.*;
import java.net.*;
import java.util.Date;


/**
 *
 * @author CryoGen
 */
public class Main extends Applet implements Runnable {
    static public URL codebase;
    
    private Thread thread;
    private Date date;
    private long millis;
    
    private int etape;
    
    private Vaisseau joueur;
    
    private Projectile [] projectiles;
    private Explosion [] explosions;    
    //private Entity [] entities;
    
    private Level level;
    private boolean gameover;
    
    private final int shotSpeed = -5;
    private final int joueurLeftSpeed = -4;
    private final int joueurRightSpeed = 4;
    private final int joueurUpSpeed = -4;
    private final int joueurDownSpeed = 2;
    
    private boolean joueurMoveLeft;
    private boolean joueurMoveRight;
    private boolean joueurMoveUp;
    private boolean joueurMoveDown;
    private boolean joueurGenerateProjectile;
    
    private Image image;
    private Graphics graphics;
         
    private Hud hud;
    
    //sons
    private Sound fire_missile;
    private Sound bonus;
    private Sound small_explosion, medium_explosion, big_explosion;
    private Sound meteor_breakup;
    //fin son
    
    
    
    public void init()
    {
        /* Init des Images */
        Item.imgWeapon1 = getImage(getCodeBase(), "PUWeapon1.png");
        Item.imgWeapon2 = getImage(getCodeBase(), "PUWeapon2.png");
        Item.score      = getImage(getCodeBase(), "PUScore.png"  );
        Item.shield     = getImage(getCodeBase(), "PUShield.png" );
        Item.clone      = getImage(getCodeBase(), "clone.png" );
        Item.invincible = getImage(getCodeBase(), "ALLWeapons.png" );
        
        Meteor.imgT11 = getImage(getCodeBase(), "meteor\\type11.png");
        Meteor.imgT12 = getImage(getCodeBase(), "meteor\\type12.png");
        Meteor.imgT13 = getImage(getCodeBase(), "meteor\\type13.png");
        Meteor.imgT21 = getImage(getCodeBase(), "meteor\\type21.png");
        Meteor.imgT22 = getImage(getCodeBase(), "meteor\\type22.png");
        Meteor.imgT23 = getImage(getCodeBase(), "meteor\\type23.png");
        Meteor.imgT31 = getImage(getCodeBase(), "meteor\\type31.png");
        Meteor.imgT32 = getImage(getCodeBase(), "meteor\\type32.png");
        Meteor.imgT33 = getImage(getCodeBase(), "meteor\\type33.png");
        
        Explosion.t16 = getImage(getCodeBase(), "explode16.png");
        Explosion.t32 = getImage(getCodeBase(), "explode32.png");
        Explosion.t64 = getImage(getCodeBase(), "explode64.png");
        
        Projectile.imgProj = getImage(getCodeBase(), "missile.png");
        
        Hud.life = getImage(getCodeBase(), "PULife.png");
        
        Vaisseau.img_clone = getImage(getCodeBase(), "vaisseau.png");
        Vaisseau.img_invincible = getImage(getCodeBase(), "vaisseau-transparent-sans-clone.png");
        Vaisseau.img_invincible_clone = getImage(getCodeBase(), "vaisseau-transparent.png");
        
        Vaisseau.img_burner = getImage(getCodeBase(), "burn.png");
        
        /* fin Init Image */
        
        /* Init des Tableau */
        projectiles = new Projectile[90];
        explosions  = new Explosion[90];
        //entities    = new Entity[50];
        /* Fin Init des tableaux */
        
        /* Init element applet */
        date = new Date();
        setBackground(Color.BLACK);
        codebase = getCodeBase();
        /* Fin Init element */
        
        /* Init jeu */
        level = new Level(this, "niveau1.txt");
        joueur = new Vaisseau(getImage(getCodeBase(), "vaisseau-sans-clone.png"), 200, 200, 88, 88, this);
        Vaisseau.clone = false;
        hud = new Hud(joueur, this);
        gameover = false;
        /* Fin Init jeu */
        
        this.fire_missile = new Sound(codebase + "sounds\\fire_missile.wav", this);
        this.bonus = new Sound(codebase + "sounds\\bonus.wav", this);
        this.small_explosion = new Sound(codebase + "sounds\\small_explosion.wav", this);
        this.medium_explosion = new Sound(codebase + "sounds\\medium_explosion.wav", this);
        this.big_explosion = new Sound(codebase + "sounds\\big_explosion.wav", this);
        this.meteor_breakup = new Sound(codebase + "sounds\\asteroid_breakup.wav", this);
    }
    
    public void start() {
        thread = new Thread(this);
        thread.start();
    }
    
    public void stop() {
        thread.stop();
    }
    
    public void destroy() {
        thread.stop();
    }
    
    
    public void run() {
        millis = date.getTime();
        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        boolean collision;
        String entity_col;
       
        
       
        
        while(true)
        {
             /* Init Level */
            
                   
            if(level.isNext())
            {
                if(level.LoadLevel(etape) == false)
                {
                    if(level.isEnd) thread.interrupt();
                    System.out.println("Erreur Main : LoadLevel | FIN DE NIVEAU ??");
                    stop();
                }else
                {
                    System.out.println("Loading Etape " + Integer.toString(etape));
                    etape++;
                }
            }
            
            for(int i = 0 ; i < level.entities.size() ; i++)
            {
                
                    if(! ((Entity)level.entities.get(i)).move_y(((Entity)level.entities.get(i)).speed_y))
                    {
                        level.entities.remove(i);
                    }
               
            }
            if(this.joueurGenerateProjectile)
            {
                new Sound(codebase + "sounds\\fire_missile.wav", this).play();
                for(int i = 0; i < projectiles.length; i++)
                {
                    if(projectiles[i] == null) {
                        projectiles[i] = joueur.generateProjectile();
                        
                        break;
                    }
                }
                
                if(Vaisseau.clone)
                {
                    for(int i = 0; i < projectiles.length; i++)
                    {
                        if(projectiles[i] == null) {
                            projectiles[i] = joueur.generateProjectilePodL();
                            
                   
                          break;
                        }
                    }
                    for(int i = 0; i < projectiles.length; i++)
                    {
                        if(projectiles[i] == null) {
                            projectiles[i] = joueur.generateProjectilePodR();
                            
                   
                          break;
                        }
                    }
                }
            
                this.joueurGenerateProjectile = false; 
            }
            for(int i = 0; i < projectiles.length; i++)
            {
                if(projectiles[i] != null)
                {
                    //on deplace le projectile
                    projectiles[i].moveProjectile(shotSpeed);
                    
                    if(projectiles[i].getY() < 0) {
                        projectiles[i] = null;
                    }
                }
            }
            
            //Deplacement joueur
            if(joueurMoveLeft){
                joueur.move_x(joueurLeftSpeed);
            }else if(joueurMoveRight){
                joueur.move_x(joueurRightSpeed);
            }
            if(joueurMoveUp){
                joueur.move_y(joueurUpSpeed);
            }else if(joueurMoveDown){
                joueur.move_y(joueurDownSpeed);
            }
            
            
            //TODO: Collision entities <-> Vaisseau
            collision = false;
            for(int i = 0 ; i < level.entities.size() ; i++)
            {
                
                
                    collision = joueur.collision((Entity)level.entities.get(i));
                    collision = (collision || ((Entity)level.entities.get(i)).collision(joueur));
                    if(collision == true)
                    {
                        //types de collision : Item, Meteor
                        entity_col = ((Entity)level.entities.get(i)).getClass().getSimpleName();
                        if(entity_col.equals("Item"))
                        {
                            //gestion collision vs -> item
                            new Sound(codebase + "sounds\\bonus.wav", this).play();
                            switch( ((Entity)level.entities.get(i)).getType() )
                            {
                                case Item.WEAPON:
                                    joueur.setTypeProj(((Entity)level.entities.get(i)).getStype());
                                    break;
                                    
                                case Item.SHIELD:
                                    joueur.modBouclier(((Entity)level.entities.get(i)).getStype());
                                    break;
                                    
                                case Item.SCORE:
                                    hud.updateScore(((Entity)level.entities.get(i)).getStype());
                                    break;
                                    
                                case Item.INVI:
                                    Vaisseau.invincible = true;
                                    break;
                                case Item.CLONE:
                                    Vaisseau.clone = true;
                                    break;
                                default:break;
                            }
                            level.entities.remove(i);
                            
                        }else if(entity_col.equals("Meteor"))
                        {
                            //gestion collision vs->Meteor
                            if(! Vaisseau.invincible)
                            {
                                joueur.modBouclier(- ((Entity)level.entities.get(i)).getStype());
                                if(joueur.getBouclier() <= 0)
                                {
                                    joueur.modVie(-1);
                                    joueur.modBouclier(200);
                                    if(joueur.getVie() <= 0)
                                    {
                                        gameover = true;
                                    }
                                }
                            }
                        }
                        
                    }
                    
                    //collisions Meteor -> projectile
                    for(int j=0 ; j < projectiles.length ; j++)
                    {
                        if(projectiles[j] != null && level.entities.size() != i && level.entities.get(i).getClass().getSimpleName().equals("Meteor"))
                        {
                            if(projectiles[j].collision((Meteor)level.entities.get(i)))
                            {
                                if(((Meteor)level.entities.get(i)).modVie(- projectiles[j].getPuissance()))
                                {
                                    hud.updateScore(((Meteor)level.entities.get(i)).getVie());
                                    level.entities.remove(i);
                                    new Sound(codebase + "sounds\\asteroid_breakup.wav", this).play();
                                    
                                }
                                
                                
                                for(int e = 0; i < explosions.length ; e++)
                                {
                                    if(explosions[e] == null){
                                    explosions[e] = projectiles[j].generateExplosion();
                                    switch(explosions[e].getType())
                                    {
                                        case 0: new Sound(codebase + "sounds\\small_explosion.wav", this).play();  hud.updateScore(10); break;
                                        case 1: new Sound(codebase + "sounds\\medium_explosion.wav", this).play(); hud.updateScore(20); break;
                                        case 2: new Sound(codebase + "sounds\\big_explosion.wav", this).play(); hud.updateScore(30); break;
                                    }
                                    break;
                                    }
                                }
                                projectiles[j] = null;
                            }
                        }
                    }
                
            }
            
            repaint();
            
            try{
                millis = date.getTime() - millis;
                if(millis >= 15) millis = 15;
                Thread.sleep(15 - millis);
            }catch(InterruptedException e) {
            }
            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
            
            level.next();
        }//Fin while(true)
    }
    
    public boolean keyDown(Event e, int key){
        if(key == Event.LEFT){
            joueurMoveLeft = true;
        }else if(key == Event.RIGHT){
            joueurMoveRight = true;
        }else if(key == Event.UP){
            joueurMoveUp = true;
        }else if(key == Event.DOWN){
            joueurMoveDown = true;
        }else if(key == 32){
            joueurGenerateProjectile = true;
        }
        return true;
    }
    
    public boolean keyUp(Event e, int key){
        if(key == Event.LEFT){
            joueurMoveLeft = false;
            joueur.setDirection(0);
        }else if(key == Event.RIGHT){
            joueurMoveRight = false;
            joueur.setDirection(0);
        }else if(key == Event.UP){
            joueurMoveUp = false;
        }else if(key == Event.DOWN){
            joueurMoveDown = false;
        }else if(key == 32){
            joueurGenerateProjectile = false;
        }
        return true;
    }
    
    
    public boolean mouseDown(Event e, int x, int y)
    {
        joueurGenerateProjectile = true;
        return true;
    }
    
    public void update(Graphics g){
        if(image == null){
            image = createImage(this.getSize().width, this.getSize().height);
            graphics = image.getGraphics();
        }
        
        //graphics.setColor(getBackground());
        //graphics.fillRect(0, 0, this.getSize().width, this.getSize().height);
        graphics.drawImage(level.bg, 0, 0, this);
        graphics.setColor(getForeground());
        paint(graphics);
        
        g.drawImage(image, 0,0, this);
    }
    
    public void paint(Graphics g){
        if(level.bgs1 != null) level.bgs1.draw(g);
        if(level.bgs2 != null) level.bgs2.draw(g);
        
        for(int i = 0 ; i < level.entities.size(); i++)
        {
            ((Entity)level.entities.get(i)).draw(g);       
            
        }
                
        for(int i = 0; i < projectiles.length; i++)
        {
            if(projectiles[i] != null) {
                projectiles[i].drawProjectile(g);
            }
            
            if(explosions[i] != null) {
                explosions[i].draw(g);
                if(explosions[i].rendered())
                    explosions[i] = null;
            }
        }
        
        joueur.draw(g);
        hud.draw(g);
        
        if(gameover)
        {
            g.drawString("GAME OVER", 300, 250);
            this.stop();
        }
    }

}
