import java.util.*;
import java.awt.*;

public class Piege extends Entite{
	
	private Entite objet=new Entite();
	
	private boolean actifPiege=false;
	private int complexitePiege=0;
	
	private boolean casse=false;//
	private String modele=new String();//
	private String nom=new String();//
	private String typeObjet=new String();//
	private boolean visible=true;//
	private String tileStr=new String();//
	private String sonActivation=new String();//
	
	private int poids=1;//
	//private String nomEquipement=new String();//
	
	private int rayon=0;
	private int puissance=0;
	
	private int resistanceMat=0;
	private int structureMat=0;
	
	private int niveau=0;
	
	
	private ArrayList boundArray=new ArrayList();
	
	private String nomE=new String();
	
	public String getNomE(){
		return nomE;
	}
	
	public Piege(Monde monde,boolean randomIn,int radius,int power,boolean actifC,int complexiteC,boolean brok,String modeleC,String name,String nameE,String typeObjetC,boolean visibleC,String tileStrC,String sndC){
		
		
		if(complexiteC-100>0){
			//niveau=Math.round((complexiteC-100)/10);
			
			niveau=Math.round((complexiteC-95)/5);
		}
		else{niveau=0;
		}
		
		
		
		
		rayon=radius;
		puissance=power;
		
		actifPiege=actifC;
		complexitePiege=complexiteC;
		casse=brok;
		modele=modeleC;
		nom=name;
		nomE=nameE;
		typeObjet=typeObjetC;
		visible=visibleC;
		tileStr=tileStrC;
		sonActivation=sndC;
		//nomEquipement=nom;
		
		
		if(getModele().compareTo("teleporttrap")==0){
			
			resistanceMat=300;
			structureMat=1000;
			poids=20;
			
			if(randomIn){
				rayon=0;
				
				//puissance=(int)(Math.abs(Math.random()*6))+1;
				//complexitePiege=(int)(Math.abs(Math.random()*250))+50;
				
				puissance=(int)(Math.random()*monde.ipp())+1;
				complexitePiege=(int)(Math.random()*monde.ipp()*20)+1;
				
				
				
				
				if(complexitePiege-100>0){
					//niveau=Math.round((complexitePiege-100)/10);
					niveau=Math.round((complexitePiege-95)/5);
				}
				else{niveau=0;
				}
			}
			
			
		}
		
		
		
		if(getModele().compareTo("explosivetrap")==0){
			
			
			resistanceMat=300;
			structureMat=1000;
			poids=5;
			
			if(randomIn){
				rayon=(int)(Math.abs(Math.random()*6))+1;
				
				
				//puissance=(int)(Math.abs(Math.random()*150))+50;
				//complexitePiege=(int)(Math.abs(Math.random()*250))+50;
				
				puissance=(int)(Math.random()*monde.ipp()*10)+1;
				complexitePiege=(int)(Math.random()*monde.ipp()*20)+1;
				
				
				if(complexitePiege-100>0){
					//niveau=Math.round((complexitePiege-100)/10);
					niveau=Math.round((complexitePiege-95)/5);
				}
				else{niveau=0;
				}
			}
			
		}
		
		
		
		if(getModele().compareTo("piketrap")==0){
			
			resistanceMat=300;
			structureMat=1000;
			poids=100;
			
			if(randomIn){
				rayon=0;
				//puissance=(int)(Math.abs(Math.random()*150))+50;
				//complexitePiege=(int)(Math.abs(Math.random()*250))+50;
				
				puissance=(int)(Math.random()*monde.ipp()*20)+1;
				complexitePiege=(int)(Math.random()*monde.ipp()*20)+1;
				
				
				if(complexitePiege-100>0){
					//niveau=Math.round((complexitePiege-100)/10);
					niveau=Math.round((complexitePiege-95)/5);
				}
				else{niveau=0;
				}
			}
			
		}
		
		
		
		if(getModele().compareTo("trou")==0){
			
			resistanceMat=100000000;
			structureMat=100000000;
			poids=100000000;
			complexitePiege=100000000;
			
			if(randomIn){
				//puissance=(int)(Math.abs(Math.random()*150))+50;
				puissance=(int)(Math.random()*monde.ipp()*10)+1;
			}
			
			if(puissance-100>0){
				//niveau=Math.round((puissance-100)/10);
				niveau=Math.round((complexitePiege-95)/5);
			}
			else{niveau=0;
			}
			
			
			
		}
		
		
			
	}
	
	
	
	//////////////////////////////////////////
	public void creationBoundArray(Monde monde, int xCentre, int yCentre, int rayon){
	
		for(int x=xCentre-rayon;x<=xCentre+rayon;x++){
			
			/// Pour empecher les nullPointers
			if(x<monde.tailleGrille-10 && x>9 && yCentre+rayon<monde.tailleGrille-10 && yCentre-rayon>9){	
				boundArray.add(new Point(x,yCentre-rayon));
				boundArray.add(new Point(x,yCentre+rayon));
			}
		}
		
		for(int y=yCentre-rayon;y<=yCentre+rayon;y++){
			if(xCentre+rayon<monde.tailleGrille-10 && xCentre-rayon>9 && y<monde.tailleGrille-10 && y>9){	
				boundArray.add(new Point(xCentre-rayon,y));
				boundArray.add(new Point(xCentre+rayon,y));
			}
		}
		
		
	
		
	}
	
	
	
	///////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////
	
	
	public void effetPiege(Entite victime,Monde monde,int coX,int coY){
		
		bruit(monde,coX,coY);
		
		
		
		
		if(getModele().compareTo("trou")==0){
		
			monde.jeuPan.messagesPanel.remplissageMessages(victime.getNom()+" tombe",false);
			monde.jeuPan.messagesPanel.remplissageMessages(victime.getNomE()+" is falling",true);
			
			if(victime.getTypeObjet().compareTo("Creature")==0){
			
				monde.grille[coX][coY].remove(victime);
			}
			
			
			
			if(victime.getClass().getName().compareTo("Personnage")==0){
				
				
				monde.voyageVertical(false);
			
				
				int degats=100;
				if((victime.getbonusDefArmure()*10)>degats){degats=0;}
				else{degats=100-(victime.getbonusDefArmure()*10);}
				
		
				victime.setCurrentHitPts(victime.getCurrentHitPts()-degats);
				if(victime.getCurrentHitPts()<=0){
					victime.setMort(monde,true,coX,coY);
				}
				
				
				monde.jeuPan.messagesPanel.remplissageMessages(victime.getNom()+" tombe et prend "+degats+" points de degats",false);
				monde.jeuPan.messagesPanel.remplissageMessages(victime.getNomE()+" falls and takes "+degats+" wound points",true);
				
			
			
			}
				
			
			
			
			setActifPiege(true);
			setVisible(true);
			setCasse(false);
			
			
			
		}
		
		
		
		
		
		
		if(getModele().compareTo("piketrap")==0){
		
		
			int degats=puissance;
			if((victime.getbonusDefArmure()*10)>degats){degats=0;}
			else{degats=puissance-(victime.getbonusDefArmure()*10);}
			
	
			victime.setCurrentHitPts(victime.getCurrentHitPts()-degats);
			if(victime.getCurrentHitPts()<=0){
				victime.setMort(monde,true,coX,coY);
			}
			
			
			monde.jeuPan.messagesPanel.remplissageMessages(victime.getNom()+" s empale et prend "+degats+" points de degats",false);
			monde.jeuPan.messagesPanel.remplissageMessages(victime.getNomE()+" is impaled and takes "+degats+" wound points",true);
			
			
			
			setActifPiege(true);
			setVisible(true);
			setCasse(false);
		
		}
		
		/////////////////////////////////////////////////////////////
		
		
		if(getModele().compareTo("teleporttrap")==0){
			
			int orientation=(int)(Math.abs(Math.random()*8))+1;
			
			int origineX=victime.getCooX();
			int origineY=victime.getCooY();
			int arriveeX=0;
			int arriveeY=0;
			
			
			
			if(orientation==1){
				arriveeX=victime.getCooX()-puissance;
				arriveeY=victime.getCooY()+puissance;
			}
			if(orientation==2){
				arriveeX=origineX;
				arriveeY=victime.getCooY()+puissance;	
			}
			if(orientation==3){
				arriveeX=victime.getCooX()+puissance;
				arriveeY=victime.getCooY()+puissance;
			}
			if(orientation==4){
				arriveeX=victime.getCooX()-puissance;
				arriveeY=origineY;
			}
			if(orientation==5){
				arriveeX=victime.getCooX()+puissance;
				arriveeY=origineY;
			}
			if(orientation==6){
				arriveeX=victime.getCooX()-puissance;
				arriveeY=victime.getCooY()-puissance;
			}
			if(orientation==7){
				arriveeX=origineX;
				arriveeY=victime.getCooY()-puissance;
			}
			if(orientation==8){
				arriveeX=victime.getCooX()+puissance;
				arriveeY=victime.getCooY()-puissance;
			}
			
			//Empeche de sortir de grille
			if(arriveeX>=monde.tailleGrille-10){arriveeX=monde.tailleGrille-11;} 
			if(arriveeX<=9){arriveeX=10;} 
			
			if(arriveeY>=monde.tailleGrille-10){arriveeY=monde.tailleGrille-11;} 
			if(arriveeY<=9){arriveeY=10;}
			
			
			
			monde.grille[victime.getCooX()][victime.getCooY()].remove(victime);
			
			victime.setCooX(arriveeX);
			victime.setCooY(arriveeY);
			
			
			monde.grille[arriveeX][arriveeY].add(victime);
				
			victime.analyseDuSol(arriveeX,arriveeY);
			
			
			///enumeration, si Obstacle, RIP (ici ce n'est pas pour le PJ, voir dans monde.tourDuMonde)
			
	        
    		if(victime.getClass().getName().compareTo("Personnage")!=0 && !monde.grille[arriveeX][arriveeY].isEmpty()){
				
				for(int i=0;i<monde.grille[arriveeX][arriveeY].size();i++){
					
		 					
		 			try{
		 					
		 					
		 				objet = (Entite) monde.grille[arriveeX][arriveeY].get(i);
	 					
	 					
						String typedelobjet=objet.getTypeObjet();
						//String strClass = (objet.getClass().getName());
						//String strModele= objet.getModele();
						if(!objet.getOuvert()&&!objet.getCasse()&&typedelobjet.compareTo("Obstacle")==0 && victime.getPasseMuraille()==false){
							monde.jeuPan.messagesPanel.remplissageMessages(victime.getNom()+" fusionne avec cet obstacle. Une mort amusante.",false);
							monde.jeuPan.messagesPanel.remplissageMessages(victime.getNomE()+"  amalgamates with this obstacle. Very nice death.",true);
							
							
							/*if(victime.getClass().getName().compareTo("Personnage")==0){
								monde.losOn=false;
							}*/
							
							victime.setMort(monde,true,arriveeX,arriveeY);
							
								
									
						}
					}
					catch(NoSuchElementException exc){};
				}
			}
			
			monde.testSiPersoDansMurOuVide();
		}
		
		
		
		
		
		///////////////////////////////////////////////////////////////////////
		
		if(getModele().compareTo("explosivetrap")==0){
			
			//// autour du piege, dans un rayon donné (qui peut être 0)
			// on enumere tous les objets
			// on leur inglige à tous les dommages du piege
			// pour les creature c'est un test de defBonus armure+Constitution // perte de pts de vie
			// pour les objets c'est un test de Resistance // perte de Structure
			
			
			
			
			creationBoundArray(monde,coX,coY,rayon);
			
			ArrayList explodedList=new ArrayList();
			
			
			
			Entite ici=new Entite();
	    	Point persoPt=new Point(coX,coY); //centre
	    	Point studyPt=new Point(coX,coY);
	    	
	    	for(int i=0;i<boundArray.size();i++){
	    		
	    		Point[] tabloPt=bresenham_line(persoPt,(Point)boundArray.get(i));
	    		int pow=puissance;
	    		
		    		for(int b=0;b<tabloPt.length;b++){
		    			
		    			studyPt=tabloPt[b];
		    			
		    			/////////////////////////////////////////////////////
							
							//parcours dans studyPt
							for(int z=0;z<monde.grille[(int)studyPt.getX()][(int)studyPt.getY()].size();z++){
								
					 			try{
					 					
					 				ici = (Entite) monde.grille[(int)studyPt.getX()][(int)studyPt.getY()].get(z);
				 					//VS CREATURES
									if(ici.getTypeObjet().compareTo("Creature")==0 || ici.getClass().getName().compareTo("Personnage")==0){
										
										if(!explodedList.contains(studyPt)){
											explosionCreaturesPerso(monde,pow,ici,(int)studyPt.getX(),(int)studyPt.getY());
										}
									}
									
									//VS OBJETS
									else{
										if(!explodedList.contains(studyPt)){
											explosionObjets(ici,monde,pow,ici,(int)studyPt.getX(),(int)studyPt.getY());
										}
									}
									
									//le premier objet ne sert ici à rien
									
									//déclenchements en chaine
									if(ici.getModele().compareTo("explosivetrap")==0 && ((int)studyPt.getX()!=coX || (int)studyPt.getY()!=coY)){
										setActifPiege(false);
										if(ici.getActifPiege()){ici.effetPiege(this,monde,(int)studyPt.getX(),(int)studyPt.getY());}	
									}
									
									
									if(ici.getTypeObjet().compareTo("Obstacle")==0 && !ici.getCasse()){
										pow=pow-(ici.getResistanceMat()+ici.getStructureMat());
										if(pow<0){pow=0;
										}
									}
									
									if(ici.getClass().getName().compareTo("Gate")==0 && !ici.getCasse() && !ici.getOuvert()){
										pow=pow-(ici.getResistanceMat()+ici.getStructureMat());
										if(pow<0){pow=0;
										}
									}
									
									//diminution puissance avec eloignement 
									//pow=pow-10;
									//if(pow<0){pow=0;
									//}
									
									
											
								}
								catch(NoSuchElementException exc){};
								
								
								
								
							}
							
							explodedList.add(studyPt);
							///////////////////////////////////////////////////////
							
						//// anim feu
						if(pow>0){monde.animGrid[(int)studyPt.getX()][(int)studyPt.getY()]=2;	
						}
						
							
		    		}
		    		
	    			
				}
		    	///////////////////////////////////:
		    	setActifPiege(false);
				setVisible(true);
				setCasse(true);
		    
		    
				

			
			
			
			
			/*
			//on cherche dans toute la grille
			// a chaque fois qu'on trouve une entite du genre recherché
			for(int x=coX-rayon;x<=coX+rayon;x++){
	        	for(int y=coY-rayon;y<=coY+rayon;y++){	
	        		
	        		
	        		
	        		
	        		
	        		//////////////////////////////////////////////////////////////////
					if(x<monde.tailleGrille-10 && x>9 && y<monde.tailleGrille-10 && y>9){	
						
						for(int i=0;i<monde.grille[x][y].size();i++){
					
		 					//
		 					
					 			try{
					 					
					 					
					 				objet = (Entite) monde.grille[x][y].get(i);
					 					
										//VS CREATURES
										if(objet.getTypeObjet().compareTo("Creature")==0 || objet.getClass().getName().compareTo("Personnage")==0){
											explosionCreaturesPerso(monde,puissance,objet,x,y);
											
										}
										
										//VS OBJETS
										else{
											explosionObjets(objet,monde,puissance,objet,x,y);
										}
										
										//le premier objet ne sert ici à rien
										
										//déclenchements en chaine
										if(objet.getTypeObjet().compareTo("Piege")==0 && (x!=coX || y!=coY)){
											
											if(objet.getActifPiege()){objet.effetPiege(this,monde,x,y);}	
										}
										
										setActifPiege(false);
										setVisible(true);
										setCasse(true);
										
								}
								catch(NoSuchElementException exc){};
								
							
						}
					}
					/////////////////////////////////////////////
					
					
					
					
				}
			}	
			*/
			
			
			
			
			
			////////////////
			
		}
		
		//Ancienne méthode
		//monde.perso.miseAjourVisuelEquipement();
		
		monde.miseAJourResumeStatsPanel();
		
		
		//////////VERIFICATION DE L'ETAT DE SANTE DU PERSONNAGE///////////
		if(monde.perso.getCurrentHitPts()<1){
			monde.perso.setMort(monde,true,0,0);	
		}
		
		if(monde.perso.getMort()==true){
			
			new ThreadSon("./sons/death.wav",0).start();
			
			monde.jeuPan.messagesPanel.remplissageMessages("VOUS ETES MORT",false);
			monde.jeuPan.messagesPanel.remplissageMessages("YOU ARE DEAD",true);
			
			//new RIP();
			
		}
		
		
		
		
			
		
	}
	
	
	
	
	public void explosionCreaturesPerso(Monde monde,int puissance, Entite objet,int x,int y){
		
		//VS CREATURES
		//
		int degats=puissance;
		if((objet.getbonusDefArmure()*10)>degats){degats=0;}
		else{degats=puissance-(objet.getbonusDefArmure()*10);}
		

		objet.setCurrentHitPts(objet.getCurrentHitPts()-degats);
		if(objet.getCurrentHitPts()<=0){
			objet.setMort(monde,true,x,y);
		}
		
		Entite objet2=new Entite();
		//Degats dans l'equipement
		if(!objet.getEquipementVect().isEmpty()){

			for(Enumeration e = objet.getEquipementVect().elements();e.hasMoreElements();){
                
 				try{	
 						
 					objet2=(Entite) e.nextElement();
 					
					//monde.jeuPan.messagesPanel.remplissageMessages(objet2.getNom());
 					explosionObjets(objet,monde,degats,objet2,x,y);
 					
 					
 				}
 				catch(NoSuchElementException exc){};
 			}
		}
		
		
	}
	
	
	
	
	public void explosionObjets(Entite porteur,Monde monde,int puissance, Entite objet,int x,int y){
		String typedelobjet=objet.getTypeObjet();
		int degats=puissance;
		if(objet.getResistanceMat()>degats){degats=0;}
		else{degats=puissance-objet.getResistanceMat();}
		
		objet.setStructureMat(objet.getStructureMat()-degats);
		
		if(objet.getStructureMat()<=0){
			objet.setCasse(true);
			
			if(objet.getClass().getName().compareTo("Arme")==0 || objet.getClass().getName().compareTo("Outil")==0){
				porteur.unequipArme(objet);
			
			}
			
			if(objet.getClass().getName().compareTo("Armure")==0){
				porteur.unequipArmure(objet);
				
			}
			
			
		}
		
		//monde.jeuPan.messagesPanel.remplissageMessages(objet.getNom()+" Res"+objet.getResistanceMat()+" prend "+degats);
		
		
		if(objet.getClass().getName().compareTo("Contenant")==0){
			//monde.jeuPan.messagesPanel.remplissageMessages("Coffre DMG "+degats);
		
		
			Entite objet2=new Entite();
			//Degats au contenu
			Vector contenu=objet.getContenu();
			if(!contenu.isEmpty()){
	
				for(Enumeration e = contenu.elements();e.hasMoreElements();){
	                
	 				try{	
	 						
	 					objet2=(Entite) e.nextElement();
	 					
						//monde.jeuPan.messagesPanel.remplissageMessages(objet2.getNom());
	 					explosionObjets(objet,monde,degats,objet2,x,y);
	 					// dans explosionObjets(objet,monde,degats,objet2,x,y); objet ne sert ici à rien
	 					
	 				}
	 				catch(NoSuchElementException exc){};
	 			}
			}
		}
								
	}




//////////////////////////////////////////////////////////////////////
	
	public boolean getActifPiege(){
		return actifPiege;
	}
	
	public void setActifPiege(boolean acttrap){
		actifPiege=acttrap;
	}
	
	public int getComplexitePiege(){
		return complexitePiege;
	}
	public void setComplexitePiege(int complex){
		complexitePiege=complex;
	}
	
	public int getPuissancePiege(){
		return puissance;
	}
	
	public int getPoids(){
		
		return poids;
	}
	
	public void setPoids(int pds){
		poids=pds;
	}
	
	
	/*
	public String getNomDequipement(){
		return nomEquipement;
	}
	
	public void setNomDequipement(String nomEquip){
		nomEquipement=nomEquip;
	}*/
	
	public String getNom(){
		return nom;
	}
	
	
	
	public void setCasse(boolean broken){
		casse=broken;
		
	}
	
	
	public boolean getCasse(){
		return casse;
	}
	
	
	
	
	public String getModele(){
		return modele;
	}
	
	
	
	public boolean getVisible(){
		return visible;
	}
	
	public void setVisible(boolean visibility){
		visible=visibility;
	}
	
	
	
	public String getTileStr(){
		
		return tileStr;
		
		
	}
	
	
	public void bruit(Monde monde,int vx,int vy){
		
		
		float vol=0;
		int px=monde.perso.getCooX();
		int py=monde.perso.getCooY();
		//int vx=this.getCooX();
		//int vy=this.getCooY();
		
		
		//System.out.println("PIEGE DECLENCHE EN "+vx+" "+vy);
		
		int dx=Math.abs(vx-px);
		int dy=Math.abs(vy-py);
		
		if(dx>dy){vol=(float)dx*(-1);
		}
		else{vol=(float)dy*(-1);
		}
		
		vol=Math.round(vol/2);
		
		if(vol<-20){vol=-20;
		}
		
		new ThreadSon(sonActivation,vol).start();
		
		
	}
	
	
	public int getNiveau(){
		return niveau;
	}
	
	public String getTypeObjet(){
		return typeObjet;
	}
	
	
	public String getSonActivation(){
		return sonActivation;
	}
	
	public int getResistanceMat(){
		return resistanceMat;
	}
	
	public void setResistanceMat(int res){
		resistanceMat=res;
	}
	
	public int getStructureMat(){
		return structureMat;
	}
	
	public void setStructureMat(int struct){
		structureMat=struct;
	}
	
	
	
	
	
    public final static Point[] bresenham_line(Point pt1, Point pt2) {
        return bresenham_line(pt1.x, pt1.y, pt2.x, pt2.y);
    }

   
    public final static Point[] bresenham_line(int x1, int y1, int x2, int y2) {
        
        int i;
        int d, x, y, ax, ay, sx, sy, dx, dy, t;

        dx = x2 - x1;
        ax = Math.abs(dx) << 1;
        sx = sign(dx);
        dy = y2 - y1;
        ay = Math.abs(dy) << 1;
        sy = sign(dy);

        t = Math.max(Math.abs(dx), Math.abs(dy)) + 1;
        Point[] ret_val = new Point[t];

        x = x1;
        y = y1;
        if (ax > ay) { /* x dominant */
            d = ay - (ax >> 1);
            for (i = 0;;) {
                ret_val[i++] = new Point(x, y);
                //ret_val[i].x = x; ret_val[i++].y = y;
                if (x == x2)
                    return ret_val;
                if (d >= 0) {
                    y += sy;
                    d -= ax;
                }
                x += sx;
                d += ay;
            }
        } else { /* y dominant */
            d = ax - (ay >> 1);
            for (i = 0;;) {
                ret_val[i++] = new Point(x, y);
                //ret_val[i].x = x; ret_val[i++].y = y;
                if (y == y2)
                    return ret_val;
                if (d >= 0) {
                    x += sx;
                    d -= ay;
                }
                y += sy;
                d += ax;
            }
        }
    }
    
    
    /**
     * Return sign of number.
     * 
     * @param x short
     * @return int sign -1, 1
     */
    public static final int sign(short x) {
        return (x < 0) ? -1 : 1;
    }

    /**
     * Return sign of number.
     * 
     * @param x int
     * @return int sign -1, 1
     */
    public static final int sign(int x) {
        return (x < 0) ? -1 : 1;
    }

    /**
     * Return sign of number.
     * 
     * @param x long
     * @return int sign -1, 1
     */
    public static final int sign(long x) {
        return (x < 0) ? -1 : 1;
    }

    /**
     * Return sign of number.
     * 
     * @param x float
     * @return int sign -1, 1
     */
    public static final int sign(float x) {
        return (x < 0f) ? -1 : 1;
    }

    /**
     * Return sign of number.
     * 
     * @param x double
     * @return int sign -1, 1
     */
    public static final int sign(double x) {
        return (x < 0d) ? -1 : 1;
    }
	
	
}