import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List;

/**
 * Die Munition die der Tower abfeuert
 * 
 * @author Marek Parucha, Yacin Boualili
 * @version 3.0_5.02.2014
 */
public class Munition extends Actor
{
    
   
    
   
    /**Power der Munition
     */
    protected int shotPower; // Power des Schusses ( Wert der dem Monster abgezogen wird)
    /**Radius der Munition
     */
    protected int radius;
    /**Hat der Tower diese Objekt schon berührt?
     */
    private boolean hasIntersected =false; //Hat der Tower diese Objekt schon berührt?
    /** X Wert des Rechten Randes
     */
    double rechterRand = TeD_World.PIX*TeD_World.NX;// X Wert des Rechten Randes
    /** Y Wert des Rechten Randes
     */
    double untererRand = TeD_World.PIX*TeD_World.NY; // Y Wert des unteren Randes
    /** Geschwindigkeit der Munition
     */
    protected int geschwind;
    
    
    
    /**Perspektivische Verschiebung in X-Richtung
     */
    private double verschiebung_X = 0.0;
    
    /**Perspektivische Verschiebung in Y-Richtung
     */
    private double verschiebung_Y = 0.0;
    
    /**Endpunkt
     */
    protected Point endPoint;
    private Point eP = new Point(true);
    
    
    
    /**Startpunkt X-Koordinate
     */
    protected double start_X;
    
    /**Startpunkt Y-Koordinate
     */
    protected double start_Y;
    
    protected int    sektor;
    
    /**Winkel den der Mittelpunkt der Turmgrundfläche mit dem Monster einschließt
     */
    protected double winkel = 0.0;
    
    protected Monsters aim;
    
    /** a nach Parabelform a*x² + b*x + c
     */
    protected double a = 0.0;
    
    /** b nach Parabelform a*x² + b*x + c
     */
    protected double b = 0.0;
    
    /** c nach Parabelform a*x² + b*x + c
     */
    protected double c = 0.0;
    
    /** a' nach Parabelform (a*x² + b*x + c)'
     */
    private double a_Deriv = 0.0;
    
    /** b' nach Parabelform (a*x² + b*x + c)'
     */
    private double b_Deriv = 0.0;
    
    /**Momentane Steigung des Geschosses
     */
    private double steigung = 0.0;
    
    /** erster Aufruf der act-Funkton?
     */
    private boolean firstRun = true;
    
    private Animation animation;
    
    private boolean kill = false;
    
    /** " " " Konstruktor der Klasse Munition " " "
     * 
     * @param 'A': a nach Parabelform a*x² + b*x + c
     * @param 'B': b nach Parabelform a*x² + b*x + c
     * @param 'C': c nach Parabelform a*x² + b*x + c
     * @param 'D': Distanz zwischen Mittelpunkt der Turmgrundfläche und Monster
     * @param 'W': Winkel den die Gerade Mittelpunkt der Turmgrundfläche ; Monster 
     *             mit der Geraden die parallel zur X-Achse liegt und durch den
     *             Mittelpunkt der Turmgrundfläche geht einschließt.
     * @param 'X': X-Koordinate des Startpunkts
     * @param 'Y': Y-Koordinate des Startpunkts
     * @param 'S': Sektor (relativ zum Turm) in den die Munition abgfeuert wird:
     *                   1 = oben    /   links
     *                   2 = oben    /   rechts
     *                   3 = unten   /   links
     *                   4 = unten   /   rechts
     */
    public Munition( double A  , double B , double C , Point D, double W, double X , double Y, int S , Monsters m , int sP, int sG, int R , Animation i)
    {
        
        
        
        
        
        a           = A;
        b           = B;
        c           = C;
        endPoint    = D;
        winkel      = W;
        start_X     = X;
        start_Y     = Y;
        sektor      = S;
        aim         = m;
        shotPower   = sP;
        geschwind   = sG;
        radius      = R;
        animation   = i;
    }

    
    /**
     * act() Methode regelt wann die Munition verschwindet, wohin sie sich bewegt und welchem Monster sie was abzieht 
     */
    public void act() 
    {
        if(!animation.isPlaying() && geschwind == 0 )
        {
            kill(false);
            return;
        }
        if(firstRun)
        {
            animation.act();
            this.setImage(animation.getImage());
            getWorld().addObject( eP , endPoint.getX() , endPoint.getY() );
            
            firstRun = false;
        }
        
        animation.act();
        this.setImage(animation.getImage());
        
        if( (eP == this.getOneIntersectingObject( Point.class ) || endPoint == this.getOneIntersectingObject( Point.class )) && radius == 1)
        {
            aim.removeLife(shotPower);
            
            if(!kill)
            {
                kill( true );
            }
            
            return;
        }
        else if(  (eP == this.getOneIntersectingObject( Point.class ) || endPoint == this.getOneIntersectingObject( Point.class )) && radius > 1 )
        {
            if(!kill)
            {
                List l=this.getObjectsInRange(radius,Monsters.class);
                int groesse = l.size();
                for(int i=0;i<groesse; i++)
                {
                    ((Monsters)l.get(i)).removeLife(shotPower);
                }
                
            }
            
            
            kill( true );
            
            return;
        }
        if (getWorld()!= null)
        {
            if(getX()==0||getX()==1||getX()==2)
            {
                kill( false );
                return;
            }
            else if(getX()==rechterRand ||getX()==rechterRand-1||getX()==rechterRand-2)
            {
                kill( false );
                return;
            }
            else if(getY()==untererRand||getY()==untererRand-1||getY()==untererRand-2)
            {
                kill( false );
                return;
            }   
            else if(getY()==0||getY()==1||getY()==2)
            {
                kill( false );
                return;
            }
        }
        if (getWorld()!= null && aim.getWorld() != null && !kill)
        {
            fly();
        }
        else if(kill)
        {
            geschwind = 0;
        }
        else
        {
            geschwind = 0;
            kill( false );
        }
    }    

    
    private void fly()
    {
        ableiten();
        if( sektor == 2 || sektor == 4 )
        {
            setRotation( (int)(getSteigungsWinkel( getDistanz_Turm() ) ));
        }
        else if( sektor == 1 || sektor == 3 )
        {
            setRotation(180-(int)(getSteigungsWinkel( getDistanz_Turm() ) ));
        }
        move(geschwind);
    }
    
    private void kill(boolean ani)
    {
        
        if(ani)
        {
            if(!kill)
            {
                animation.start();
                kill = true;
            }
            
        }
        if( !animation.isPlaying() || !ani )
        {
            getWorld().removeObject(eP);
            getWorld().removeObject(this);
        }
    }
    
    private double getSteigung( double X )
    {
        return ( ( a_Deriv * (double)X ) + b_Deriv );
    }
    
    private double getSteigungsWinkel( double X )
    {
        return (double)Math.toDegrees( Math.atan( ( -1 ) * getSteigung( X ) ) ) ;
    }
    
    private void ableiten()
    {
        this.a_Deriv = 2*a;
        this.b_Deriv = b;
    }
    
    /**
     * brechnet die distanz mit dem Satz des Pytagoras
     */
    private double getDistanz_Turm()
    {
       return Math.abs( this.getX()-start_X );
    }
   
}
