///Licensed under Creative Commons Attribution 4.0 License, Written by Clemens Winter and Vladislav Nachev
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace Exploitation
{
    /// <summary>
    /// Agent specification
    /// </summary>
    public class Agent
    {
        Physiology physiology;
        Memory memory;
        Decision decision;
        Personality personality;
        int alternationrepeats;
        int[] altSequence;
        TransferParticles transferParticles;
        Perception perception;
        int xPos;
        int yPos;
        int id;
        
         internal Agent(Physiology physiology, Memory memory, Perception perception, Personality personality, Decision decision, int id,
             int alternationrepeats, int[] altSequence)
        {
            this.physiology = physiology;
            this.memory = memory;
            this.perception = perception;
            this.decision = decision;
            this.personality = personality;
            this.id = id;
            this.alternationrepeats = alternationrepeats;
            this.altSequence = altSequence;
        }

        // event can be requested as either a free choice or ...
        internal EventRequest EventRequest(long time)
        {
            long timenextvisit = physiology.IntervalToNextEvent() + time;

            return new EventRequest(timenextvisit, null, decision.RessourceGoal(timenextvisit), this, physiology.MealMax, transferParticles);
        }
        // ... a forced alternation choice
        internal EventRequest AltEventRequest(long time, int altvisit, int[] altSequence)
        {
            long timenextvisit = physiology.IntervalToNextEvent() + time;
            return new EventRequest(timenextvisit, null, decision.RessourceAltGoal(timenextvisit, altvisit, altSequence), this, physiology.MealMax, transferParticles);
        }

        /// <summary>
        /// Evaluate event outcome and store outcome and other event-related info into memory
        /// </summary>
        /// <param name="reward">reward properties struct</param>
        /// <param name="pos">resource position</param>
        /// <param name="ressource">resource object</param>
        /// <param name="transferParticles">pollen, with its haploid genotype</param>
        /// <param name="time">current time in seconds</param>
        internal void EventFeedback(RewardStruct reward, Pos pos, Ressource ressource, TransferParticles transferParticles, long time)
        {
            this.xPos = ressource.XPos;
            this.yPos = ressource.YPos;
            long intervalLastVisit = memoryrecord.LastVisitTime(time);
            physiology.ReturnActionOutcome(reward, intervalLastVisit);
            memory.StoreEvent(new MemoryStruct(time, ressource, reward, pos));
            this.transferParticles = transferParticles;
            
        }


        public void ResetMemoryContent(Ressource[] ressources)
        {
            memory.ResetMemoryContent(ressources);
        }


        
        public int XPos { get { return xPos; } }
        public int YPos { get { return yPos; } }
        public int ID { get { return id; } }
        public Memory memoryrecord { get { return memory; } }
        public Perception Perception { get { return perception ; } }
        public Physiology Physiology { get { return physiology; } }
        public Personality Personality { get { return personality; } }
        public int altvisits { get { return alternationrepeats; } }
        public int[] AltSequence { get { return altSequence; } }
    }
}
