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

/**
 * A spaceship controlled by the player -- white or black.
 * 
 * @author Jannis Andrija Schnitzer, Martin Schend
 * @version 2011-01-21
 */
public class ManuallyControlledSpaceship  extends Spaceship
{
    public static final int BASE_HP = 1000;
    
    /**
     * How many hitpoints a collision with another spaceship should cost.
     */
    public static final int COLLISION = 100;
    
    /**
     * How many pixels the spaceship should move per turn when a movement key is pressed.
     */
    public static final int MOVEMENT = 10;
    
    /**
     * If the spaceship should automatically fire whenever possible.
     */
    protected boolean autofire;
    
    /**
     * Should the player be allowed to move the spaceship up and down?
     */
    protected boolean mayMoveUpAndDown;
    
    protected class Keys
    {
        public String left = "";
        public String right = "";
        public String up = "";
        public String down = "";
        public String shoot = "";
    }
    
    /**
     * Contains strings with the keys for all possible actions.
     * 
     * @see #Keys
     * @see #act()
     */
    protected Keys keys;
    
    public ManuallyControlledSpaceship(int the_level)
    {
        super(the_level);
        /* Don't be destroyed when we hit the border. Right now, this is actually just protection from coding
         * errors. But who knows what the future brings?
         */
        disappear = false;
        
        hitpoints = max_hitpoints = level * BASE_HP;
        
        setupImages();
        setBlinkFile("ShipHit.png");
        setMaxBlink(5);
        
        setupKeys();
        
        autofire = false;
    }
    
    protected void setupImages()
    {
        if (side == InvadersWorld.WHITE) 
            this.setImage("WhiteShip.png");
        else
            this.setImage("BlackShip.png");
    }
    
    /**
     * Set keys according to the side we're on.
     */
    protected void setupKeys()
    {
        keys = new Keys();
        if (side == InvadersWorld.WHITE)
        {
            keys.left = "left";
            keys.right = "right";
            keys.up = "up";
            keys.down = "down";
            keys.shoot = "space";
        }
        else if (side == InvadersWorld.BLACK)
        {
            keys.left = "a";
            keys.right = "d";
            keys.up = "w";
            keys.down = "s";
            keys.shoot = "x";
        }
    }
    
    public void setSide(int the_side)
    {
        side = the_side;
        setupImages();
        setupKeys();
    }
    public int getSide()
    {
        return side;
    }
    
    public void setMayMoveUpAndDown(boolean may)
    {
        mayMoveUpAndDown = may;
    }
    public boolean getMayMoveUpAndDown()
    {
        return mayMoveUpAndDown;
    }
    
    /**
     * Do quantum object duties, then check what the player wants the spaceship to do.
     */
    public void act() 
    {
        super.act();
        
        if (Greenfoot.isKeyDown(keys.left))
            moveLeft();
        else if (Greenfoot.isKeyDown(keys.right))
            moveRight();
        
        if (Greenfoot.isKeyDown(keys.up))
            moveUp();
        else if (Greenfoot.isKeyDown(keys.down))
            moveDown();
        
        if (autofire || Greenfoot.isKeyDown(keys.shoot))
            fire();
    }
    
    public void moveLeft()
    {
        setLocation(getX()-MOVEMENT, getY());
    }
    public void moveRight()
    {
        setLocation(getX()+MOVEMENT, getY());
    }
    public void moveUp()
    {
        if (!mayMoveUpAndDown)
            return;
        setLocation(getX(), getY()-MOVEMENT); // I hate that weird coordinate system
    }
    public void moveDown()
    {
        if (!mayMoveUpAndDown)
            return;
        setLocation(getX(), getY()+MOVEMENT);
    }
    
    /**
     * Update the health bar in InvadersWorld.
     * 
     * @see InvadersWorld.setHealthBar()
     */
    public void updateHealth()
    {
        InvadersWorld myWorld = (InvadersWorld) getWorld();
        myWorld.setHealthBar(side, hitpoints);
    }
    
    public void addHitpoints(int n_hitpoints)
    {
        super.addHitpoints(n_hitpoints);
        updateHealth();
    }
    public void removeHitpoints(int n_hitpoints)
    {
        super.removeHitpoints(n_hitpoints);
        updateHealth();
    }
    public void setHitpoints(int n_hitpoints)
    {
        super.setHitpoints(n_hitpoints);
        updateHealth();
    }
    
    /**
     * Before destruction: tell world to announce the winner (which is the other side, if this is destroyed).
     */
    public void beforeDestruction()
    {
        int winner;
        InvadersWorld world = (InvadersWorld) getWorld();
        if (side == InvadersWorld.WHITE)
            winner = InvadersWorld.BLACK;
        else if (side == InvadersWorld.BLACK)
            winner = InvadersWorld.WHITE;
        else
            winner = -1;
        world.gameOverNextTurn(winner);
    }
    
    public boolean hit(AIControlledSpaceship s)
    {
        if (s.getSide() != side) // not one of our ships
            removeHitpoints(COLLISION);
        return true;
    }
}
