<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using Messages.Server;
using ScriptableObjects;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;

/// <summary>
/// For server.
/// </summary>
public class NetworkTabManager : MonoBehaviour {

	private static NetworkTabManager networkTabManager;
	public static NetworkTabManager Instance => networkTabManager;

	[SerializeField]
	private GameObjectList netTabs = null;
	public GameObjectList NetTabs => netTabs;

	[SerializeField]
	private GameObjectList netEntries = null;
	public GameObjectList NetEntries => netEntries;

	private readonly Dictionary<NetTabDescriptor, NetTab> openTabs = new Dictionary<NetTabDescriptor, NetTab>();

	public List<ConnectedPlayer> GetPeepers(GameObject provider, NetTabType type)
	{
		var descriptor = Tab( provider, type );
		if ( !openTabs.ContainsKey( descriptor ) ) {
			return new List<ConnectedPlayer>();
		}
		var info = openTabs[descriptor];
		if ( info.IsUnobserved ) {
			return new List<ConnectedPlayer>();
		}
		return info.Peepers.ToList();
	}

	private void Awake()
	{
		if (networkTabManager == null)
		{
			networkTabManager = this;
		}
		else
		{
			Destroy(this);
		}
	}

	private void OnEnable()
	{
		SceneManager.activeSceneChanged += OnLevelFinishedLoading;
	}

	private void OnDisable()
	{
		SceneManager.activeSceneChanged -= OnLevelFinishedLoading;
	}

	private void OnLevelFinishedLoading(Scene oldScene, Scene newScene)
	{
		Instance.ResetManager();
	}

	void ResetManager()
	{
		//Reset manager on round start:
		foreach ( var tab in Instance.openTabs )
		{
				Destroy(tab.Value.gameObject);
		}

		Instance.openTabs.Clear();
	}

	/// Used when a new dynamic element is added/removed
	public void Rescan(NetTabDescriptor tabDescriptor)
	{
		var netTab = Get(tabDescriptor);
		if (netTab != null)
		{
			netTab.RescanElements();
		}
	}

	///Create new NetworkTabInfo if it doesn't exist, otherwise add player to it
	public void Add(NetTabDescriptor tabDescriptor, GameObject player)
	{
		if (tabDescriptor.Equals( NetTabDescriptor.Invalid ))
		{
			return;
		}

		if (!openTabs.TryGetValue(tabDescriptor, out var tab))
		{
			//Spawning new one
			tab = tabDescriptor.Spawn(transform);
			if (tab == null)
			{
				return;
			}
			openTabs.Add( tabDescriptor, tab );
		}
		tab.AddPlayer( player );
	}
	public void Add(GameObject provider, NetTabType type, GameObject player)
	{
		Add( Tab(provider, type), player );
	}

	public void Remove(GameObject provider, NetTabType type, GameObject player)
	{
		Remove( Tab( provider, type ), player );
	}

	/// remove player from NetworkTabInfo, keeping the tab
	public void Remove(NetTabDescriptor tabDescriptor, GameObject player)
	{
		if (!openTabs.ContainsKey(tabDescriptor)) return;

		NetTab t = openTabs[tabDescriptor];
		t.RemovePlayer(player);
//		if ( t.Peepers.Count == 0 ) {
//			t.gameObject.SetActive( false );
//		}
	}

	/// <summary>
	/// Completely remove the nettab from existence, removing all players from it.
	/// </summary>
	/// <param name="provider"></param>
	/// <param name="type"></param>
	public void RemoveTab(GameObject provider, NetTabType type)
	{
		var ntd = Tab(provider, type);
		openTabs.TryGetValue(ntd, out var netTab);
		if (netTab != null)
		{
			//remove all peepers
			//safe copy so we can concurrently modify it
			var peepers = netTab.Peepers.Select(cp => cp.GameObject).ToList();
			foreach (var peeper in peepers)
			{
				Remove(provider, type, peeper);
				TabUpdateMessage.Send( peeper, provider, type, TabAction.Close );
			}
			// completely get rid of the tab
			openTabs.Remove(ntd);
			Destroy(netTab.gameObject);
		}
	}

	public NetTab Get(GameObject provider, NetTabType type)
	{
		return Get(Tab(provider, type));
	}

	public NetTab Get(NetTabDescriptor tabDescriptor)
	{
		return openTabs.ContainsKey(tabDescriptor) ? openTabs[tabDescriptor] : null; //NetworkTabInfo.Invalid;
	}

	private static NetTabDescriptor Tab( GameObject provider, NetTabType type )
	{
		return provider == null ? NetTabDescriptor.Invalid : new NetTabDescriptor(provider, type);
	}
}

public struct NetTabDescriptor
{
	public static readonly NetTabDescriptor Invalid = new NetTabDescriptor(null, NetTabType.None);
	private readonly GameObject provider;
	private readonly NetTabType type;

	public NetTabDescriptor(GameObject provider, NetTabType type)
	{
		this.provider = provider;
		this.type = type;
		if (type == NetTabType.None && this.provider != null)
		{
			Logger.LogError( "You forgot to set a proper NetTabType in your new tab!\n" +<commit_msg>add object name to log<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using Messages.Server;
using ScriptableObjects;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;

/// <summary>
/// For server.
/// </summary>
public class NetworkTabManager : MonoBehaviour {

	private static NetworkTabManager networkTabManager;
	public static NetworkTabManager Instance => networkTabManager;

	[SerializeField]
	private GameObjectList netTabs = null;
	public GameObjectList NetTabs => netTabs;

	[SerializeField]
	private GameObjectList netEntries = null;
	public GameObjectList NetEntries => netEntries;

	private readonly Dictionary<NetTabDescriptor, NetTab> openTabs = new Dictionary<NetTabDescriptor, NetTab>();

	public List<ConnectedPlayer> GetPeepers(GameObject provider, NetTabType type)
	{
		var descriptor = Tab( provider, type );
		if ( !openTabs.ContainsKey( descriptor ) ) {
			return new List<ConnectedPlayer>();
		}
		var info = openTabs[descriptor];
		if ( info.IsUnobserved ) {
			return new List<ConnectedPlayer>();
		}
		return info.Peepers.ToList();
	}

	private void Awake()
	{
		if (networkTabManager == null)
		{
			networkTabManager = this;
		}
		else
		{
			Destroy(this);
		}
	}

	private void OnEnable()
	{
		SceneManager.activeSceneChanged += OnLevelFinishedLoading;
	}

	private void OnDisable()
	{
		SceneManager.activeSceneChanged -= OnLevelFinishedLoading;
	}

	private void OnLevelFinishedLoading(Scene oldScene, Scene newScene)
	{
		Instance.ResetManager();
	}

	void ResetManager()
	{
		//Reset manager on round start:
		foreach ( var tab in Instance.openTabs )
		{
				Destroy(tab.Value.gameObject);
		}

		Instance.openTabs.Clear();
	}

	/// Used when a new dynamic element is added/removed
	public void Rescan(NetTabDescriptor tabDescriptor)
	{
		var netTab = Get(tabDescriptor);
		if (netTab != null)
		{
			netTab.RescanElements();
		}
	}

	///Create new NetworkTabInfo if it doesn't exist, otherwise add player to it
	public void Add(NetTabDescriptor tabDescriptor, GameObject player)
	{
		if (tabDescriptor.Equals( NetTabDescriptor.Invalid ))
		{
			return;
		}

		if (!openTabs.TryGetValue(tabDescriptor, out var tab))
		{
			//Spawning new one
			tab = tabDescriptor.Spawn(transform);
			if (tab == null)
			{
				return;
			}
			openTabs.Add( tabDescriptor, tab );
		}
		tab.AddPlayer( player );
	}
	public void Add(GameObject provider, NetTabType type, GameObject player)
	{
		Add( Tab(provider, type), player );
	}

	public void Remove(GameObject provider, NetTabType type, GameObject player)
	{
		Remove( Tab( provider, type ), player );
	}

	/// remove player from NetworkTabInfo, keeping the tab
	public void Remove(NetTabDescriptor tabDescriptor, GameObject player)
	{
		if (!openTabs.ContainsKey(tabDescriptor)) return;

		NetTab t = openTabs[tabDescriptor];
		t.RemovePlayer(player);
//		if ( t.Peepers.Count == 0 ) {
//			t.gameObject.SetActive( false );
//		}
	}

	/// <summary>
	/// Completely remove the nettab from existence, removing all players from it.
	/// </summary>
	/// <param name="provider"></param>
	/// <param name="type"></param>
	public void RemoveTab(GameObject provider, NetTabType type)
	{
		var ntd = Tab(provider, type);
		openTabs.TryGetValue(ntd, out var netTab);
		if (netTab != null)
		{
			//remove all peepers
			//safe copy so we can concurrently modify it
			var peepers = netTab.Peepers.Select(cp => cp.GameObject).ToList();
			foreach (var peeper in peepers)
			{
				Remove(provider, type, peeper);
				TabUpdateMessage.Send( peeper, provider, type, TabAction.Close );
			}
			// completely get rid of the tab
			openTabs.Remove(ntd);
			Destroy(netTab.gameObject);
		}
	}

	public NetTab Get(GameObject provider, NetTabType type)
	{
		return Get(Tab(provider, type));
	}

	public NetTab Get(NetTabDescriptor tabDescriptor)
	{
		return openTabs.ContainsKey(tabDescriptor) ? openTabs[tabDescriptor] : null; //NetworkTabInfo.Invalid;
	}

	private static NetTabDescriptor Tab( GameObject provider, NetTabType type )
	{
		return provider == null ? NetTabDescriptor.Invalid : new NetTabDescriptor(provider, type);
	}
}

public struct NetTabDescriptor
{
	public static readonly NetTabDescriptor Invalid = new NetTabDescriptor(null, NetTabType.None);
	private readonly GameObject provider;
	private readonly NetTabType type;

	public NetTabDescriptor(GameObject provider, NetTabType type)
	{
		this.provider = provider;
		this.type = type;
		if (type == NetTabType.None && this.provider != null)
		{
			Logger.LogError($"You forgot to set a proper NetTabType in your new tab on {this.provider.ExpensiveName()}!\n" +
{'fraction_non_alphanumeric': 0.10735865343116098, 'fraction_numerical': 0.00021579628830384117, 'mean_word_length': 4.1437291897891235, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5014418', 'n_tokens_mistral': 3121, 'n_tokens_neox': 2869, 'n_words': 777}