/*
 * Ant.java
 *
 * Created on 07 October 2006, 15:45
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package ants;

import ants.event.AntEvent;
import ants.event.AntListener;
import ants.event.PickedUpFoodAntEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
import java.util.Vector;

/**
 *
 * @author James Hamilton
 */
public class Ant extends MyObject implements Runnable {
 
    private Thread move;
    private int currentDirection = GridSquare.getRandomDirection();
    private Food food = null;
    
    private GridSquare lastGridSquare = null;
    private GridSquare previousGridSquare = null;
    private HashSet<GridSquare> dontVisit = new HashSet<GridSquare>();
    
    private Color color = Color.red;
    
    
    /** Creates a new instance of Ant */
    public Ant() {
    }
    
    public Ant(Ant ant) {
         super(ant.getGridSquare()); 
    }
    
    public Ant(GridSquare gridSquare) {
        super(gridSquare);
        Random generator = new Random();
         color = new Color(generator.nextInt( 255 ), generator.nextInt( 255 ),generator.nextInt( 255 ));
    
      //  setGridSquare(gridSquare); 
    }
    
    private Vector<AntListener> listeners = new Vector<AntListener>();
    
    public void addAntListener(AntListener listener) {
        listeners.add(listener);
    }
    
    public void notifyListeners(AntEvent e) {
        for(AntListener listener : listeners)
            listener.antEventHandler(e);
    }
   
    public boolean onTrail() {
        return getGridSquare().getPheromoneStrength() > 0;
    }
    
    public boolean onOwnTrail() {
        return getGridSquare().getPheromone().laidBy(this);
    }
    

    public GridSquare getNextGridSquare() {
        
        GridVector squares;// = getGridSquare().getGridSquares(1).getFreeGridSquares();
        squares = getGridSquare().getGridSquaresInDirection(currentDirection).getFreeGridSquares(); 
        
        if(carryingFood()) squares = squares.getEmptyGridSquares();
        
        GridSquare currentGridSquare = getGridSquare();
        GridSquare nextGridSquare = null;
        
        if(getGridSquare().isNest()) {
            if(carryingFood()) {
                Grid.getInstance().getNest().addAnt(this);    
            }else{
                squares = getGridSquare().getGridSquares(1).getFreeGridSquares();
                
                if(squares.getPheromoneStrength(PheromoneParticle.TOWARD_NEST) > 0) {
                    
                    squares = squares.getPheromoneGridSquares();

                    GridVector towardsNest = squares.getPheromoneGridSquares(PheromoneParticle.TOWARD_NEST);
                    GridVector awayFromNest = squares.getPheromoneGridSquares(PheromoneParticle.AWAY_FROM_NEST);

                
                        if(towardsNest.size() > 0) {
                            Collections.sort(squares, GridSquare.PheromoneStrengthComparator);

                            nextGridSquare = squares.firstElement();                        
                        }
                        /*else if(awayFromNest.size() > 0) {
                             if(awayFromNest.getPheromoneGridSquares(this).size() > 0) {
                                squares = awayFromNest.getPheromoneGridSquares(this);
                            }else{
                                 squares = awayFromNest;
                            }

                            Collections.sort(squares, GridSquare.PheromoneStrengthComparator);

                            nextGridSquare = squares.firstElement();
                        }*/
                   
                }
                
                if(nextGridSquare == null) nextGridSquare = squares.getRandomGridSquare();
                currentDirection = getGridSquare().getDirectionOf(nextGridSquare);                               
            }
        }else{
           
            if(squares.size() == 0) {
                //if there is nowhere 2 go infront, look behind.
                currentDirection = GridSquare.getOppositeDirection(currentDirection);
                squares = getGridSquare().getGridSquaresInDirection(currentDirection).getFreeGridSquares(); 
            }
            
            boolean changeDirection = false;
            
            if(squares.size() == 0 || (onTrail() && carryingFood())) {
                //if there is nowhere 2 go behind, look look sidewards.
                squares = getGridSquare().getGridSquares(1).getFreeGridSquares();      
                changeDirection = true;
            }
            
            if(carryingFood() && squares.containsNest()) {
                nextGridSquare = Grid.getInstance().getNest().getGridSquare();
            }else if(!carryingFood() && squares.containsFood() ) {
                squares = squares.getFoodGridSquares();
                
                nextGridSquare = squares.getRandomGridSquare();
            }else if(!carryingFood() && squares.getFoodStrength() > 0) {
                squares = squares.getFoodStrengthGridSquares();
                
                Collections.sort(squares, GridSquare.FoodStrengthComparator);
                
                nextGridSquare = squares.firstElement();
            }else if(carryingFood() && squares.getPheromoneStrength() > 0) {
                squares = squares.getPheromoneGridSquares();
                
                GridVector towardsNest = squares.getPheromoneGridSquares(PheromoneParticle.TOWARD_NEST);
                GridVector awayFromNest = squares.getPheromoneGridSquares(PheromoneParticle.AWAY_FROM_NEST);
                
                if(carryingFood()) {
                    if(towardsNest.size() > 0) {
                        Collections.sort(squares, GridSquare.PheromoneStrengthComparator);
                        
                        nextGridSquare = squares.firstElement();                        
                    }else if(awayFromNest.size() > 0) {
                         if(awayFromNest.getPheromoneGridSquares(this).size() > 0) {
                            squares = awayFromNest.getPheromoneGridSquares(this);
                        }else{
                             squares = awayFromNest;
                        }
                         
                        Collections.sort(squares, GridSquare.PheromoneStrengthComparator);
                        
                        nextGridSquare = squares.firstElement();
                    }
                }
                
                Collections.sort(squares, GridSquare.PheromoneStrengthComparator);
                
                nextGridSquare = squares.getRandomGridSquare(true);                
                
                
            }else if(squares.size() == 3) {
                nextGridSquare = squares.getMiddleGridSquare();
            }else if(squares.size() > 0) {
                nextGridSquare = squares.getRandomGridSquare();
            }else{
                //dont move
            }
            
            if(changeDirection)
                currentDirection = getGridSquare().getDirectionOf(nextGridSquare);
            
        }
        
        return nextGridSquare;
    }
    
    public synchronized void move() {
        
       
           if(carryingFood()) {

             getGridSquare().getPheromone().increaseStrength(this, PheromoneParticle.TOWARD_NEST);               

        }else{


            getGridSquare().getPheromone().increaseStrength(this, PheromoneParticle.AWAY_FROM_NEST);   

        }     
        GridVector squares = getGridSquare().getGridSquares(1).getFreeGridSquares();
        GridSquare currentGridSquare = getGridSquare();
        GridSquare nextGridSquare = getNextGridSquare();
        
         
  


       
        
        if(nextGridSquare != null) {
            if(nextGridSquare.containsFood()) carry(nextGridSquare.getFood());
            setGridSquare(nextGridSquare, false);
        }
        
     


    }
   
    public void carry(Food food) {
      //  System.out.println("Carrying...");
       // Grid.getInstance().printStats();
       
        try {
            notifyListeners(new PickedUpFoodAntEvent(this));
            this.setFood(food);
            food.getGridSquare().recalculateFoodStrength(false);
            food.getGridSquare().setObject(null);
            
            turnBack();
            //setGridSquare(getPreviousGridSquare());
            
            food.setGridSquare(null);
            

        }catch (RuntimeException e) {
           // System.out.println("Already gone!");
        }
    }
    
    public boolean carryingFood() {
        return getFood() != null;
    }
    
    public void turnBack() {
            if(getPreviousGridSquare() != null) {
                currentDirection = getGridSquare().getDirectionOf(getPreviousGridSquare());
            }        
    }
    
    public void run() {
        //Call the move method while the Thread is running. And sleep for a time based on iSpeed.
        while(move != null) {
            try {
                move();
          
                move.sleep(200);
            }catch (InterruptedException e) {}
        }
    }
    
    /**
     * Start or stop the ant moving.
     * @param start true to start, false to stop.
     */
    public void start(boolean start) {
        if(start) start(); else stop();
    }
    
    /**
     * Start the ant moving.
     */
    public void start() {
        //Create and start a new Thread.
        move = new Thread(this);
      //  move.setDaemon(true);
        move.start();
    }
    
    public void pause() {
        if(move == null) start();
        else stop();
    }
    
    /**
     * Stop the rectangle moving.
     */
    public void stop() {
        move = null;
    }

    
    public Color getColor() {
        if(food == null) 
            return color;
        else
            return Color.YELLOW;
    }

    public Food getFood() {
        return food;
    }

    public void setFood(Food food) {
        this.food = food;
    }
    
    public String toString() {
        return "Ant" 
		+ getGridSquare().getGridSquares(1).getGridSquaresInDirection(
			getGridSquare(), currentDirection).getFreeGridSquares() 
		+ ";direction: " + currentDirection;
    }
    
    public void draw(Graphics g) {
        super.draw(g);

    
    }

    public GridSquare getPreviousGridSquare() {
        return previousGridSquare;
    }

    public void setPreviousGridSquare(GridSquare previousGridSquare) {
        this.previousGridSquare = previousGridSquare;
    }
 
    public void setGridSquare(GridSquare gridSquare, boolean setDirection) {
        if(setDirection) 
               currentDirection = getGridSquare().getDirectionOf(gridSquare);
        
        setPreviousGridSquare(getGridSquare());
        super.setGridSquare(gridSquare);
    }
    
    public void setGridSquare(GridSquare gridSquare) {
            setGridSquare(gridSquare, false);
    }
}

