using System;
using System.Collections.Generic;
using UnityEngine;
namespace Mirror
{
    /// 
    /// Component that controls visibility of networked objects for players.
    /// Any object with this component on it will not be visible to players more than a (configurable) distance away.
    /// 
    // Deprecated 2021-07-13
    [Obsolete(NetworkVisibilityObsoleteMessage.Message)]
    [AddComponentMenu("Network/NetworkProximityChecker")]
    [RequireComponent(typeof(NetworkIdentity))]
    [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-proximity-checker")]
    public class NetworkProximityChecker : NetworkVisibility
    {
        /// 
        /// The maximum range that objects will be visible at.
        /// 
        [Tooltip("The maximum range that objects will be visible at.")]
        public int visRange = 10;
        /// 
        /// How often (in seconds) that this object should update the list of observers that can see it.
        /// 
        [Tooltip("How often (in seconds) that this object should update the list of observers that can see it.")]
        public float visUpdateInterval = 1;
        public override void OnStartServer()
        {
            InvokeRepeating(nameof(RebuildObservers), 0, visUpdateInterval);
        }
        public override void OnStopServer()
        {
            CancelInvoke(nameof(RebuildObservers));
        }
        void RebuildObservers()
        {
            netIdentity.RebuildObservers(false);
        }
        /// 
        /// Callback used by the visibility system to determine if an observer (player) can see this object.
        /// If this function returns true, the network connection will be added as an observer.
        /// 
        /// Network connection of a player.
        /// True if the player can see this object.
        public override bool OnCheckObserver(NetworkConnection conn)
        {
            return Vector3.Distance(conn.identity.transform.position, transform.position) < visRange;
        }
        /// 
        /// Callback used by the visibility system to (re)construct the set of observers that can see this object.
        /// Implementations of this callback should add network connections of players that can see this object to the observers set.
        /// 
        /// The new set of observers for this object.
        /// True if the set of observers is being built for the first time.
        public override void OnRebuildObservers(HashSet observers, bool initialize)
        {
            // if force hidden then return without adding any observers.
            // 'transform.' calls GetComponent, only do it once
            Vector3 position = transform.position;
            // brute force distance check
            // -> only player connections can be observers, so it's enough if we
            //    go through all connections instead of all spawned identities.
            // -> compared to UNET's sphere cast checking, this one is orders of
            //    magnitude faster. if we have 10k monsters and run a sphere
            //    cast 10k times, we will see a noticeable lag even with physics
            //    layers. but checking to every connection is fast.
            foreach (NetworkConnectionToClient conn in NetworkServer.connections.Values)
            {
                if (conn != null && conn.identity != null)
                {
                    // check distance
                    if (Vector3.Distance(conn.identity.transform.position, position) < visRange)
                    {
                        observers.Add(conn);
                    }
                }
            }
        }
    }
}