package modelling;

import sema.Agent;
import sema.Element;
import modelling.Satisfactor;

/**
 * Agent able to eat other elements.
 */
public class EatingAgent extends Agent {
    
    
    /**
     * Creates a new instance of eatable agent with fixed reserves and consomptions of food.
     */
    public EatingAgent(sema.World world, sema.Area area, float delay, java.awt.Image image) {
        super(world, area , delay, image);
        this.hungrylevel = new IsHungry(10, 0, 30);
        this.consomption = new Consuming(60,3);
    }
    
    
    /**
     * Satisfactor informing on the feeding level.
     */
    protected class IsHungry extends Satisfactor {
        
        
        /**
         * Constructor for a countable hunger.
         */
        public IsHungry(float hunger, float hungryFloor, float hungryCeil){
            super();
            this.hunger = hunger;
            this.hungryFloor = hungryFloor;
            this.hungryCeil = hungryCeil;
            this.unfiniteHungry = false;
        }
        
        
        /**
         * Constructor for an infinite hunger
         */
        public IsHungry(){
            this.unfiniteHungry = true;
        };
        
        protected float hunger;
        protected float hungryFloor;
        protected float hungryCeil;
        protected boolean unfiniteHungry;
        
        
        
        /**
         * Returns wether the agent may still eat.
         */
        public boolean isSatisfying(){
            return (hunger > hungryCeil)|| unfiniteHungry ;
        }
        
        /**
         * Informs of the achievement of this goal.
         */
        public int heuristic(){
            return (int) Math.floor(hungryCeil - hunger);
        }
        
        
        /**
         * Return the amongs of food avaiable.
         */
        public float getReserves() {
            return (float) (hunger - hungryFloor);
        }
        
        /**
         * Allows to set the current hunger.
         */
        public void changeHunger(float difference){
            hunger += difference;
        }
    }
    
    
    /**
     * Action making the hunger regulary increase.
     */
    protected class Consuming extends Action {
        
        public Consuming(float delay, float among){
            super(Math.random()*20);
            this.delay = delay;
            this.among = among;
        }
        
        private float delay;
        private float among;
        
        protected float step() {
            getHungryLevel().changeHunger(delay);
            return among;
        }
    }
    
    
    protected IsHungry hungrylevel;
    protected Consuming consomption;
    
    /**
     *
     */
    protected IsHungry getHungryLevel() {
        return hungrylevel;
    }
    
    protected Action getConsomption() {
        return consomption ;
    }
    
    
    /**
     * Allows to get an among of nutrition.
     */
    protected void eat(float x) {
        hungrylevel.changeHunger(x);
    }
    /**
     * Allows to consum an among of nutrition. 
     */
    protected void consums(float x) {
        hungrylevel.changeHunger(- x);
    }
    
    /**
     * Action of eating a given element.
     */
    protected class EatElement extends Action {
        
        public EatElement(Element goal){
            this.goal = goal;
        }
        /**
         * Eated element.
         */
        protected Element goal;
        /**
         * One step of the eating. Controls if it is still possible, and eat.
         */
        protected float step() {
            
                if (world.nature.getDistance(EatingAgent.this, goal) > 2 && !getHungryLevel().isSatisfying())
                    return -1;
                else
                try{ Eatable a = (Eatable) goal;
                    if (a.canEat(EatingAgent.this))
                        getHungryLevel().changeHunger(a.eaten(EatingAgent.this));
                    return (float) Math.random() * 10;
                
            } catch (Exception e) {
                return -1;
            }
        }
    }
    
}
