/// <summary>
    /// Auxiliar method used from ModeDB through BroadcastMessage. Handles the reception of new ModeDB information in the pedestrian knowledge.
    /// </summary>
    /// <param name="information">Tuple containing the ModeInfo object and an integer indicating the mode.</param>
    public void NewMessagefromModeDBReceived(Tuple <ModeInfo, int> information)
    {
        if (tellMeWhatYouAreDoing)
        {
            Debug.Log("Got a message!");
        }

        if (suscribedToModeDB && information.Item2 == mode)
        {
            ModeInfo mInfo = information.Item1;

            foreach (var m in currentModeInfoKnowledge)
            {
                if (mInfo.GetId().Equals(m.GetId()) && !mInfo.Equals(m) && mInfo.GetTimeCreated() > m.GetTimeCreated())
                {
                    if (tellMeWhatYouAreDoing)
                    {
                        Debug.Log("Message received from mode db: " + mInfo.ToString());
                    }

                    //Copy mode (not referencing!)
                    currentModeInfoKnowledge[m.index] = new ModeInfo(mInfo.GetId(), mInfo.GetTimeOfArrival());
                    currentModeInfoKnowledge[m.index].SetStatus(mInfo.GetStatus());
                    currentModeInfoKnowledge[m.index].index = m.index;
                }
            }

            RumourInfo rInfo = new RumourInfo("rumour" + mInfo.GetId(), mInfo, 1.0f);
            rumour = new Tuple <RumourInfo, int>(rInfo, information.Item2);

            InvokeRepeating("SpreadRumour", 1, 1.0f + Random.Range(0.0f, 1.0f));

            newKnowledgeToBeCheckedbyController = true;
        }
    }
    /// <summary>
    /// Private auxiliar method. From the knowledge of the pedestrian, checks if there is a mode available soon.
    /// </summary>
    /// <returns>True if there is a mode available soon, False otherwise.</returns>
    private bool IsModeAvailableSoon()
    {
        float    distanceToMode;
        ModeInfo nextMode = knowledge.NextAvailableMode();

        if (nextMode != null)
        {
            float timeOfArrival = nextMode.GetTimeOfArrival();

            //Calculates the distance to the mode station
            if (knowledge.mode == 1)
            {
                distanceToMode = Vector3.Distance(this.transform.position,
                                                  steering.busStation.position);
            }
            else if (knowledge.mode == 2)
            {
                distanceToMode = Vector3.Distance(this.transform.position,
                                                  steering.metroStation.position);
            }
            else
            {
                return(true);
            }

            //Calculates the time remaining until the mode arrival
            float timeRemaining = timeOfArrival - (distanceToMode / steering.navAgent.speed) - Time.time;

            //Check if mode will be available soon depending on the pedestrian tolerance for waiting
            bool modeAvailableSoon =
                (timeRemaining > 0) && (timeOfArrival < (Time.time + knowledge.delayTolerance * 3600.0f));

            //Mark mode as missed if the pedestrian cannot make it to the station in time
            if (!modeAvailableSoon)
            {
                knowledge.MarkModeAsMissed(nextMode.index);
            }

            if (tellMeWhatYouAreDoing)
            {
                Debug.Log("Time of arrival of next mode: " + timeOfArrival);
                Debug.Log("Time right now: " + Time.time);
                Debug.Log("My tolerance: " + knowledge.delayTolerance * 3600.0f);
                Debug.Log("Distance to mode: " + distanceToMode / steering.navAgent.speed);
                Debug.Log("Time I have to arrive there: " + timeRemaining);
            }

            return(modeAvailableSoon);
        }
        else
        {
            return(false);
        }
    }
    /// <summary>
    /// Private auxiliar method. Calculates the time to go to the mode station from the closest study point in order to arrive there in time.
    /// </summary>
    private void CalculateWhenToGoToMode()
    {
        ModeInfo m = knowledge.NextAvailableMode();

        if (m != null)
        {
            knowledge.timeToGoToMode  = m.GetTimeOfArrival() - (Vector3.Distance(steering.ChooseClosestStudyPoint(), steering.metroStation.position) / steering.navAgent.speed);
            knowledge.timeToGoToMode -= 600; //leave 10 min before
        }
        else
        {
            //There are no more modes so far, I'll stay at the library!
            knowledge.timeToGoToMode = float.MaxValue;
        }
    }
    /// <summary>
    /// Auxiliar method used from ModeDB through BroadcastMessage. Handles the reception of a new rumour in the pedestrian knowledge.
    /// </summary>
    /// <param name="information">Tuple containing the RumourInfo object and an integer indicating the mode.</param>
    public void NewRumourReceived(Tuple <RumourInfo, int> information)
    {
        if (information.Item2 == mode)
        {
            RumourInfo newRumour = information.Item1;

            if (!newRumour.GetId().Equals(rumour.Item1.GetId()) &&
                rumourSusceptibility > Random.Range(0.0f, 1.0f) &&
                newRumour.GetCredibility() > Random.Range(0.0f, 1.0f))
            {
                ModeInfo mInfo = (ModeInfo)newRumour.GetRumour();

                foreach (var m in currentModeInfoKnowledge)
                {
                    if (mInfo.GetId().Equals(m.GetId()) && !mInfo.Equals(m) && mInfo.GetTimeCreated() > m.GetTimeCreated())
                    {
                        //Copy mode (not referencing!)
                        currentModeInfoKnowledge[m.index] = new ModeInfo(mInfo.GetId(), mInfo.GetTimeOfArrival());
                        currentModeInfoKnowledge[m.index].SetStatus(mInfo.GetStatus());
                        currentModeInfoKnowledge[m.index].index = m.index;
                    }
                }

                // Spread message around
                float rumourCredibility = newRumour.GetCredibility() - 0.1f;

                if (rumourCredibility > 0.0f)
                {
                    RumourInfo rInfo = new RumourInfo(newRumour.GetId(), newRumour.GetRumour(), rumourCredibility);
                    rumour = new Tuple <RumourInfo, int>(rInfo, information.Item2);
                    InvokeRepeating("SpreadRumour", 1, 1.0f + Random.Range(0.0f, 1.0f));
                }

                newKnowledgeToBeCheckedbyController = true;
            }
        }
    }
    /// <summary>
    /// Compares the current knowledge of the pedestrian with ModeDB and updates the information. Takes also the next available mode from the ModeDB.
    /// </summary>
    public void UpdateKnowledgeFromModeDB()
    {
        if (mode == 1)
        {
            foreach (var m in currentModeInfoKnowledge)
            {
                ModeInfo modefromDB = mdb.GetBusInfoWithId(m.GetId());
                if (modefromDB != null && !modefromDB.Equals(mdb))
                {
                    //Copy mode (not referencing!)
                    currentModeInfoKnowledge[m.index] = new ModeInfo(modefromDB.GetId(), modefromDB.GetTimeOfArrival());
                    currentModeInfoKnowledge[m.index].SetStatus(modefromDB.GetStatus());
                    currentModeInfoKnowledge[m.index].index = m.index;
                }
            }
        }
        else
        {
            foreach (var m in currentModeInfoKnowledge)
            {
                ModeInfo modefromDB = mdb.GetMetroInfoWithId(m.GetId());
                if (modefromDB != null && !modefromDB.Equals(mdb))
                {
                    //Copy mode (not referencing!)
                    currentModeInfoKnowledge[m.index] = new ModeInfo(modefromDB.GetId(), modefromDB.GetTimeOfArrival());
                    currentModeInfoKnowledge[m.index].SetStatus(modefromDB.GetStatus());
                    currentModeInfoKnowledge[m.index].index = m.index;
                }
            }
        }

        GetNextModeFromDB();
    }