Decompiled source of MusicCurator v0.1.3

MusicCurator/MusicCurator.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BombRushRadio;
using CommonAPI;
using CommonAPI.Phone;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Reptile;
using Reptile.Phone;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("MusicCurator")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Music app features for BRC")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MusicCurator")]
[assembly: AssemblyTitle("MusicCurator")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MusicCurator
{
	public class BRRHelper
	{
		private static bool hasRanBefore;

		private static MusicTrack addedTrack;

		public static void AddMissingTrackToAudios(MusicTrack missedTrack)
		{
			if (!BombRushRadio.Audios.Contains(MusicCuratorPlugin.missingStageTrack))
			{
				if (hasRanBefore)
				{
					BombRushRadio.Audios.Remove(addedTrack);
				}
				BombRushRadio.Audios.Insert(0, missedTrack);
				hasRanBefore = true;
				addedTrack = missedTrack;
			}
		}
	}
	internal class MCSettings
	{
		public static ConfigEntry<bool> instantShuffle;

		public static ConfigEntry<bool> alwaysSkipMixtapes;

		public static ConfigEntry<bool> reshuffleOnLoop;

		public static ConfigEntry<string> customPlaylistNamesUnsplit;

		public static ConfigEntry<string> keybindsSkipUnsplit;

		public static ConfigEntry<string> keybindsQueueUnsplit;

		public static List<string> customPlaylistNames;

		public static List<KeyCode> keybindsQueue;

		public static List<KeyCode> keybindsSkip;

		public static ConfigEntry<string> keybindsShuffleUnsplit;

		public static List<KeyCode> keybindsShuffle;

		public static ConfigEntry<string> keybindsPauseUnsplit;

		public static List<KeyCode> keybindsPause;

		public static ConfigEntry<bool> allMixtapes;

		public static ConfigEntry<bool> playlistTracksNoExclude;

		public static ConfigEntry<bool> skipRepeatInPlaylists;

		public static ConfigEntry<bool> alwaysInstantShuffle;

		public static void BindSettings(ConfigFile Config)
		{
			customPlaylistNamesUnsplit = Config.Bind<string>("1. Settings", "Custom Playlist Names", "", "List of replacement playlist names, seperated by commas. Spaces are allowed. Names are sorted from top to bottom in the playlist app (first name replaces New Playlist 1, second replaces New Playlist 2, etc.)");
			instantShuffle = Config.Bind<bool>("1. Settings", "Instant Shuffle", true, "Instantly set the music app to shuffle all tracks on startup.");
			alwaysSkipMixtapes = Config.Bind<bool>("1. Settings", "Skip Mixtapes By Default", true, "Automatically blocklist all mixtapes when starting a new save or resetting the blocklist.");
			allMixtapes = Config.Bind<bool>("1. Settings", "Always Load All Mixtapes", true, "Whether or not to add the Hideout mixtape in stages outside of the Hideout (or the Chapter 6 mixtape in the Hideout). Ensures playlists can include and play either track on all stages.");
			reshuffleOnLoop = Config.Bind<bool>("1. Settings", "Reshuffle Playlist on Loop", true, "If true, \"Shuffle and play\" re-shuffles a shuffled playlist every time it loops. If false, \"Shuffle and play\" shuffles the playlist once before looping the shuffled queue.");
			playlistTracksNoExclude = Config.Bind<bool>("1. Settings", "Playlists Ignore Blocklist", true, "If true, playlists can play blocklisted tracks. If false, blocklisted tracks are always skipped, including those in a playlist.");
			skipRepeatInPlaylists = Config.Bind<bool>("1. Settings", "Playlists Ignore Repeatable Tracks", true, "If true, repeatable tracks (the stage mixtapes) don't loop if they're played within a playlist. If false, repeatable tracks will loop forever, even in a playlist. They must be manually skipped to advance in the playlist.");
			alwaysInstantShuffle = Config.Bind<bool>("1. Settings", "Always Instant Shuffle", false, "If true, the music player will instantly shuffle every time the player enters a new area, rather than just on startup. Not recommended if playing with MusicCurator's patched BombRushRadio.");
			keybindsSkipUnsplit = Config.Bind<string>("2. Keybinds", "Skip Keybinds", "Semicolon, JoystickButton9", "List of KeyCodes that can be pressed to skip/blocklist tracks, separated by commas.");
			keybindsQueueUnsplit = Config.Bind<string>("2. Keybinds", "Queue Keybinds", "Quote, JoystickButton8", "List of KeyCodes that can be pressed to queue up tracks, separated by commas.");
			keybindsShuffleUnsplit = Config.Bind<string>("2. Keybinds", "Quick Toggle Shuffle Keybinds", "JoystickButton6, LeftBracket", "List of KeyCodes that can be pressed to quickly toggle shuffling, separated by commas. Only works if the music app is open.");
			keybindsPauseUnsplit = Config.Bind<string>("2. Keybinds", "Pause Music Keybinds", "F13, Pause", "List of KeyCodes that can be pressed to pause the current track, separated by commas.");
			customPlaylistNamesUnsplit.SettingChanged += UpdateSettingsEvent;
			keybindsSkipUnsplit.SettingChanged += UpdateSettingsEvent;
			keybindsQueueUnsplit.SettingChanged += UpdateSettingsEvent;
			keybindsShuffleUnsplit.SettingChanged += UpdateSettingsEvent;
			keybindsPauseUnsplit.SettingChanged += UpdateSettingsEvent;
		}

		public static void UpdateSettingsEvent(object sender, EventArgs args)
		{
			UpdateSettings();
		}

		public static void UpdateSettings()
		{
			customPlaylistNames = SplitStringByCommas(customPlaylistNamesUnsplit.Value);
			keybindsQueue = KeyCodeListFromList(SplitStringByCommas(keybindsQueueUnsplit.Value));
			keybindsSkip = KeyCodeListFromList(SplitStringByCommas(keybindsSkipUnsplit.Value));
			keybindsShuffle = KeyCodeListFromList(SplitStringByCommas(keybindsShuffleUnsplit.Value));
			keybindsPause = KeyCodeListFromList(SplitStringByCommas(keybindsPauseUnsplit.Value));
		}

		public static KeyCode StringToKeyCode(string input)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (Enum.TryParse<KeyCode>(input, ignoreCase: true, out KeyCode result))
			{
				return result;
			}
			return (KeyCode)0;
		}

		public static List<string> SplitStringByCommas(string input)
		{
			return input.Replace(", ", ",").Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList();
		}

		public static List<KeyCode> KeyCodeListFromList(List<string> input)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			List<KeyCode> list = new List<KeyCode>();
			foreach (string item in input)
			{
				list.Add(StringToKeyCode(item));
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(Phone))]
	internal class PhonePatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("TurnOff")]
		public static void TurnOffPostfix_ResetAppOptions()
		{
			MusicCuratorPlugin.selectedPlaylist = -1;
			MusicCuratorPlugin.appSelectedTrack = -1;
		}
	}
	[HarmonyPatch(typeof(MusicPlayer))]
	internal class MusicPlayerPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("EvaluateRepeatingMusicTrack")]
		public static void EVRPostfix(MusicPlayer __instance, ref bool __result)
		{
			if (MusicCuratorPlugin.skipping || (MCSettings.skipRepeatInPlaylists.Value && MusicCuratorPlugin.playlistTracks.Contains(__instance.musicTrackQueue.CurrentMusicTrack)))
			{
				__result = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("PlayNext")]
		public static void PlayNextPostfix_OverrideNextTrack(MusicPlayer __instance)
		{
			if (MusicCuratorPlugin.loopingSingleTrackIndex >= 0)
			{
				MusicTrack musicTrack = __instance.GetMusicTrack(MusicCuratorPlugin.loopingSingleTrackIndex);
				if (!MusicCuratorPlugin.IsInvalidTrack(musicTrack))
				{
					MusicCuratorPlugin.PlayTrack(musicTrack);
					return;
				}
				MusicCuratorPlugin.loopingSingleTrackIndex = -1;
				MusicCuratorPlugin.SetAppShuffle(shuffling: true);
			}
			else if (MusicCuratorPlugin.queuedTracks.Any())
			{
				MusicTrack targetTrack = MusicCuratorPlugin.queuedTracks[0];
				MusicCuratorPlugin.PlayTrack(targetTrack);
				MusicCuratorPlugin.queuedTracks.RemoveAt(0);
			}
			else
			{
				if (!MusicCuratorPlugin.playlistTracks.Any())
				{
					return;
				}
				MusicTrack val = MusicCuratorPlugin.playlistTracks[0];
				bool flag = MusicCuratorPlugin.IsInvalidTrack(val) || !__instance.musicTrackQueue.currentMusicTracks.Contains(val) || (!MCSettings.playlistTracksNoExclude.Value && MusicCuratorPlugin.excludedTracks.Contains(val));
				if (flag)
				{
					int num = 0;
					while (flag && num <= MusicCuratorPlugin.playlistTracks.Count)
					{
						num++;
						MusicCuratorPlugin.playlistTracks.RemoveAt(0);
						MusicCuratorPlugin.playlistTracks.Add(val);
						val = MusicCuratorPlugin.playlistTracks[0];
						flag = MusicCuratorPlugin.IsInvalidTrack(val) || !__instance.musicTrackQueue.currentMusicTracks.Contains(val) || (!MCSettings.playlistTracksNoExclude.Value && MusicCuratorPlugin.excludedTracks.Contains(val));
					}
					if (num > MusicCuratorPlugin.playlistTracks.Count)
					{
						MusicCuratorPlugin.playlistTracks.Clear();
						MusicCuratorPlugin.currentPlaylistIndex = -1;
						return;
					}
				}
				MusicCuratorPlugin.PlayTrack(val);
				MusicCuratorPlugin.playlistTracks.RemoveAt(0);
				MusicCuratorPlugin.playlistTracks.Add(val);
				if ((Object)(object)val == (Object)(object)MusicCuratorPlugin.playlistStartingTrack && MCSettings.reshuffleOnLoop.Value && MusicCuratorPlugin.musicPlayer.shuffle)
				{
					MusicCuratorPlugin.LoadPlaylistIntoQueue(MusicCuratorPlugin.currentPlaylistIndex, MusicCuratorPlugin.shufflingPlaylist);
					if ((Object)(object)MusicCuratorPlugin.playlistTracks[0] == (Object)(object)val)
					{
						MusicCuratorPlugin.playlistTracks.RemoveAt(0);
						MusicCuratorPlugin.playlistTracks.Add(val);
					}
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("PlayFrom")]
		public static void PlayFromPostfix_PlaylistHandling(int index, int playbackSamples, MusicPlayer __instance)
		{
			if (!MusicCuratorPlugin.ContinuingStageTrack && MusicCuratorPlugin.PlayerUsingMusicApp())
			{
				MusicCuratorPlugin.queuedTracks.Clear();
				MusicCuratorPlugin.playlistTracks.Clear();
				MusicCuratorPlugin.currentPlaylistIndex = -1;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("SetShuffle")]
		public static void SetShufflePostfix_PlaylistShuffle(bool value, MusicPlayer __instance)
		{
			if (value != MusicCuratorPlugin.shufflingPlaylist)
			{
				MusicCuratorPlugin.shufflingPlaylist = value;
				MusicCuratorPlugin.ReorderPlaylistInQueue(value);
			}
		}
	}
	[HarmonyPatch(typeof(MusicTrackQueue))]
	internal class MusicQueuePatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("ClearTracks")]
		public static void ClearTracksPostfix_AllMixtapes(MusicTrackQueue __instance)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			if (MCSettings.allMixtapes.Value)
			{
				MusicTrack musicTrackByID = Core.Instance.AudioManager.MusicLibraryPlayer.GetMusicTrackByID((MusicTrackID)6);
				MusicTrack chapterMusic = Core.Instance.chapterMusic.GetChapterMusic(Story.GetCurrentObjectiveInfo().chapter);
				MusicCuratorPlugin.missingStageTrack = (((int)Utility.GetCurrentStage() == 5) ? chapterMusic : musicTrackByID);
				if (PlaylistSaveData.excludedTracksCarryOver.Contains(MusicCuratorPlugin.TrackToSongID(MusicCuratorPlugin.missingStageTrack)))
				{
					MusicCuratorPlugin.excludedTracks.Add(MusicCuratorPlugin.missingStageTrack);
				}
				if (MusicCuratorPlugin.hasBRR && (Object)(object)MusicCuratorPlugin.missingStageTrack != (Object)null)
				{
					BRRHelper.AddMissingTrackToAudios(MusicCuratorPlugin.missingStageTrack);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("UpdateMusicQueueForStage")]
		public static bool RefreshingPrefix_AllMixtapes(MusicTrack trackToPlay, MusicTrackQueue __instance)
		{
			if ((Object)(object)MusicCuratorPlugin.missingStageTrack == (Object)null || MusicCuratorPlugin.hasBRR || __instance.currentMusicTracks.Contains(MusicCuratorPlugin.missingStageTrack) || !MCSettings.allMixtapes.Value)
			{
				return true;
			}
			__instance.currentMusicTracks.Add(MusicCuratorPlugin.missingStageTrack);
			if (PlaylistSaveData.excludedTracksCarryOver.Contains(MusicCuratorPlugin.TrackToSongID(MusicCuratorPlugin.missingStageTrack)))
			{
				MusicCuratorPlugin.excludedTracks.Add(MusicCuratorPlugin.missingStageTrack);
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("SelectNextTrack")]
		public static bool NTPrefix_SkipBlocklisted(MusicTrackQueue __instance)
		{
			if (__instance.AmountOfTracks <= 0)
			{
				return false;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			bool flag = false;
			while (num3 < __instance.indexQueue.QueueCount)
			{
				num3++;
				num2++;
				if (num2 + __instance.indexQueue.indexQueue.IndexOf(__instance.currentTrackIndex) >= __instance.indexQueue.indexQueue.Count)
				{
					num2 = -__instance.indexQueue.indexQueue.IndexOf(__instance.currentTrackIndex);
				}
				num = __instance.indexQueue.GetNextInQueue(__instance.currentTrackIndex, num2);
				bool flag2 = MusicCuratorPlugin.currentPlaylistIndex != -1 && MusicCuratorPlugin.playlistTracks.Contains(__instance.GetMusicTrack(num)) && MCSettings.playlistTracksNoExclude.Value;
				if (!MusicCuratorPlugin.excludedTracks.Contains(__instance.GetMusicTrack(num)) && !flag2)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				num = __instance.indexQueue.GetNextInQueue(__instance.currentTrackIndex, 1);
			}
			int previousInQueue = __instance.indexQueue.GetPreviousInQueue(__instance.currentTrackIndex, (int)__instance.nPreviousTracksBuffered);
			__instance.EvaluateNextTrack(num);
			__instance.EvaluateTrackToUnload(previousInQueue);
			return false;
		}
	}
	[HarmonyPatch(typeof(MusicPlayerTrackButton))]
	internal class TrackButtonPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("ConstantUpdate")]
		public static void ConstantUpdatePostfix(MusicPlayerTrackButton __instance)
		{
			if (!((PhoneScrollButton)__instance).IsHidden)
			{
				MusicCuratorPlugin.UpdateButtonColor(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("SetMusicApp")]
		public static void SetupPostfix_CreateLabel(MusicPlayerTrackButton __instance)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = ((Component)__instance.m_TitleLabel).GetComponentsInChildren<TextMeshProUGUI>().LastOrDefault();
			if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)__instance.m_TitleLabel)
			{
				TextMeshProUGUI val2 = Object.Instantiate<TextMeshProUGUI>(__instance.m_TitleLabel, ((TMP_Text)__instance.m_TitleLabel).transform);
				((TMP_Text)val2).margin = new Vector4(0f, 0f, 0f, 0f);
				((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
				((TMP_Text)val2).text = "";
				((TMP_Text)val2).fontSize = ((TMP_Text)val2).fontSize * 2f;
				((TMP_Text)val2).transform.position = ((Component)__instance.m_Disc).transform.position;
			}
		}
	}
	[HarmonyPatch(typeof(AppMusicPlayer))]
	internal class MusicAppPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnAppDisable")]
		public static void OnMusicAppDisable_SaveExclusions()
		{
			MusicCuratorPlugin.SaveExclusions();
		}

		[HarmonyPrefix]
		[HarmonyPatch("ToggleShuffle")]
		public static bool ToggleShuffle_LoopSingleTrack(ref bool value, AppMusicPlayer __instance)
		{
			if (value != __instance.GameMusicPlayer.GetShuffle() && MusicCuratorPlugin.PlayerUsingMusicApp())
			{
				if (MusicCuratorPlugin.loopingSingleTrackIndex >= 0 && value)
				{
					MusicCuratorPlugin.loopingSingleTrackIndex = -1;
					value = false;
				}
				else if (!value && __instance.GameMusicPlayer.GetShuffle())
				{
					MusicCuratorPlugin.loopingSingleTrackIndex = __instance.GameMusicPlayer.CurrentTrackIndex;
				}
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("SetShuffleIconImage")]
		public static void SetShuffleIconImagePostfix(AppMusicPlayer __instance)
		{
			if (MusicCuratorPlugin.loopingSingleTrackIndex >= 0)
			{
				Image shuffleIconImageSelected = __instance.shuffleIconImageSelected;
				Sprite sprite = (__instance.shuffleIconImageUnselected.sprite = MusicCuratorPlugin.loopingSingleTrackSprite);
				shuffleIconImageSelected.sprite = sprite;
			}
		}
	}
	[HarmonyPatch(typeof(StageManager))]
	internal class SMPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(StageManager), "StartMusicForStage", new Type[]
		{
			typeof(Stage),
			typeof(int)
		})]
		public static bool SMFSPrefix(ref Stage stage, int playbackSamples, StageManager __instance)
		{
			MusicCuratorPlugin.ContinuingStageTrack = true;
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StageManager), "StartMusicForStage", new Type[]
		{
			typeof(Stage),
			typeof(int)
		})]
		[HarmonyPriority(200)]
		public static void SMFSPostfix(Stage stage, int playbackSamples, StageManager __instance)
		{
			MusicCuratorPlugin.ContinuingStageTrack = false;
			MusicCuratorPlugin.LoadPlaylists(PlaylistSaveData.playlists);
			List<MusicTrack> excludedTracks = MusicCuratorPlugin.excludedTracks;
			IMusicPlayer musicPlayer = __instance.musicPlayer;
			bool flag = excludedTracks.Contains(((MusicPlayer)((musicPlayer is MusicPlayer) ? musicPlayer : null)).musicTrackQueue.CurrentMusicTrack);
			bool flag2 = false;
			IMusicPlayer musicPlayer2 = __instance.musicPlayer;
			bool shuffle = ((MusicPlayer)((musicPlayer2 is MusicPlayer) ? musicPlayer2 : null)).shuffle;
			if (MCSettings.instantShuffle.Value && (!MusicCuratorPlugin.hasInstantShuffledAlready || MCSettings.alwaysInstantShuffle.Value))
			{
				flag = true;
				if (MusicCuratorPlugin.hasInstantShuffledAlready)
				{
					flag2 = true;
				}
				MusicCuratorPlugin.SetAppShuffle(shuffling: true);
				MusicCuratorPlugin.hasInstantShuffledAlready = true;
			}
			if (flag)
			{
				MusicCuratorPlugin.SkipCurrentTrack();
				IMusicPlayer musicPlayer3 = __instance.musicPlayer;
				((MusicPlayer)((musicPlayer3 is MusicPlayer) ? musicPlayer3 : null)).playbackSamples = 0;
			}
			MusicCuratorPlugin.LoadExclusions();
			if (flag2)
			{
				MusicCuratorPlugin.SetAppShuffle(shuffle);
			}
		}
	}
	[HarmonyPatch(typeof(BaseModule))]
	internal class ReloadMainMenu
	{
		[HarmonyPatch("LoadMainMenuScene")]
		[HarmonyPostfix]
		private static void LoadingMenu_ResetVars()
		{
			MusicCuratorPlugin.resetVariables();
		}
	}
	public class TracksHeaderApp : CustomApp
	{
		public Transform overlayInstance;

		public void CreateAndSaveIconlessTitleBar(string title, float fontSize = 80f)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			Transform val = Object.Instantiate<Transform>(((Component)((App)this).MyPhone.GetAppInstance<AppGraffiti>()).transform.Find("Overlay"));
			Transform val2 = ((Component)val).transform.Find("Icons");
			Object.Destroy((Object)(object)((Component)val2.Find("GraffitiIcon")).gameObject);
			Transform val3 = val2.Find("HeaderLabel");
			val3.localPosition = new Vector3(140f, val3.localPosition.y, val3.localPosition.z);
			Object.Destroy((Object)(object)((Component)val3).GetComponent<TMProLocalizationAddOn>());
			TextMeshProUGUI component = ((Component)val3).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = title;
			((TMP_Text)component).fontSize = fontSize;
			((TMP_Text)component).fontSizeMax = fontSize;
			((TMP_Text)component).enableAutoSizing = true;
			val.SetParent(((Component)this).transform, false);
			overlayInstance = val;
		}
	}
	public class AppPlaylists : CustomApp
	{
		private static Sprite IconSprite;

		public static void Initialize()
		{
			IconSprite = TextureUtility.LoadSprite(Path.Combine(MusicCuratorPlugin.Instance.Directory, "MC-PlaylistIcon.png"));
			PhoneAPI.RegisterApp<AppPlaylists>("playlists", IconSprite);
		}

		public override void OnReleaseLeft()
		{
			((App)this).MyPhone.ReturnToHome();
		}

		public override void OnAppEnable()
		{
			MusicCuratorPlugin.ClearEmptyPlaylists();
			MusicCuratorPlugin.LoadPlaylists(PlaylistSaveData.playlists);
			MusicCuratorPlugin.selectedPlaylist = -1;
			SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton("Create new playlist...");
			SimplePhoneButton obj = val;
			((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppNewPlaylist));
			});
			base.ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Manage queue/blocklist...");
			SimplePhoneButton obj2 = val;
			((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppManageQueueAndExclusions));
			});
			base.ScrollView.AddButton((PhoneButton)(object)val);
			int[] array = Enumerable.Range(0, MusicCuratorPlugin.playlists.Count).ToArray();
			foreach (int playlistName in array)
			{
				string text = ((MusicCuratorPlugin.currentPlaylistIndex == playlistName) ? "> " : "");
				string text2 = (MusicCuratorPlugin.PlaylistAnyInvalidTracks(playlistName) ? " (!)" : "");
				val = PhoneUIUtility.CreateSimpleButton(text + MusicCuratorPlugin.GetPlaylistName(playlistName) + " (" + MusicCuratorPlugin.playlists[playlistName].Count + ")" + text2);
				SimplePhoneButton obj3 = val;
				((PhoneButton)obj3).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj3).OnConfirm, (Action)delegate
				{
					MusicCuratorPlugin.selectedPlaylist = playlistName;
					((App)this).MyPhone.OpenApp(typeof(AppSelectedPlaylist));
				});
				base.ScrollView.AddButton((PhoneButton)(object)val);
			}
			((App)this).OnAppEnable();
		}

		public override void OnAppDisable()
		{
			base.ScrollView.RemoveAllButtons();
			((App)this).OnAppDisable();
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).CreateTitleBar("Playlists", IconSprite, 80f);
			base.ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
			MusicCuratorPlugin.selectedPlaylist = -1;
		}
	}
	public class AppManageQueueAndExclusions : TracksHeaderApp
	{
		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppManageQueueAndExclusions>("queue/exclusions", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			((App)this).OnAppEnable();
		}

		public override void OnAppDisable()
		{
			((App)this).OnAppDisable();
		}

		public override void OnAppInit()
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			((CustomApp)this).OnAppInit();
			CreateAndSaveIconlessTitleBar("Manage queue/ blocklist");
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
			SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton("Clear queue");
			SimplePhoneButton obj = val;
			((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
			{
				MusicCuratorPlugin.playlistTracks.Clear();
				MusicCuratorPlugin.currentPlaylistIndex = -1;
				MusicCuratorPlugin.queuedTracks.Clear();
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Reset blocklist");
			SimplePhoneButton obj2 = val;
			((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
			{
				MusicCuratorPlugin.excludedTracks.Clear();
				MusicCuratorPlugin.SaveExclusions();
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Delete all playlists");
			((TMP_Text)val.Label).faceColor = Color32.op_Implicit(Color.red);
			val.LabelSelectedColor = Color.red;
			val.LabelUnselectedColor = Color.red;
			SimplePhoneButton obj3 = val;
			((PhoneButton)obj3).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj3).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppDeleteAllPlaylists));
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
		}
	}
	public class AppNewPlaylist : CustomApp
	{
		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppNewPlaylist>("new playlist", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			if (MusicCuratorPlugin.queuedTracks.Any())
			{
				SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton("New playlist from queue");
				((PhoneButton)val).OnConfirm = (Action)Delegate.Combine(((PhoneButton)val).OnConfirm, (Action)delegate
				{
					if (MusicCuratorPlugin.queuedTracks.Any())
					{
						MusicCuratorPlugin.selectedPlaylist = MusicCuratorPlugin.CreatePlaylist();
						foreach (MusicTrack queuedTrack in MusicCuratorPlugin.queuedTracks)
						{
							MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Add(queuedTrack);
						}
						MusicCuratorPlugin.SavePlaylists();
						MusicCuratorPlugin.queuedTracks.Clear();
						MusicCuratorPlugin.selectedPlaylist = -1;
					}
					((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
				});
				base.ScrollView.AddButton((PhoneButton)(object)val);
			}
			SimplePhoneButton val2 = PhoneUIUtility.CreateSimpleButton("Select playlist tracks");
			SimplePhoneButton obj = val2;
			((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
			{
				MusicCuratorPlugin.selectedPlaylist = MusicCuratorPlugin.CreatePlaylist();
				AppPlaylistTracklist.creatingPlaylist = true;
				((App)this).MyPhone.OpenApp(typeof(AppPlaylistTracklist));
			});
			base.ScrollView.AddButton((PhoneButton)(object)val2);
			val2 = PhoneUIUtility.CreateSimpleButton("Cancel");
			SimplePhoneButton obj2 = val2;
			((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
			});
			base.ScrollView.AddButton((PhoneButton)(object)val2);
			((App)this).OnAppEnable();
		}

		public override void OnAppDisable()
		{
			base.ScrollView.RemoveAllButtons();
			((App)this).OnAppDisable();
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).CreateIconlessTitleBar("New Playlist", 80f);
			base.ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}
	}
	public class AppSelectedPlaylist : TracksHeaderApp
	{
		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppSelectedPlaylist>("selected playlist", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			CreateAndSaveIconlessTitleBar(MusicCuratorPlugin.GetPlaylistName(MusicCuratorPlugin.selectedPlaylist));
			bool flag = MusicCuratorPlugin.PlaylistAllInvalidTracks(MusicCuratorPlugin.selectedPlaylist) || (!MCSettings.playlistTracksNoExclude.Value && MusicCuratorPlugin.PlaylistAllExcludedTracks(MusicCuratorPlugin.selectedPlaylist));
			SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton("Shuffle and loop playlist");
			if (flag)
			{
				((TMP_Text)val.Label).faceColor = Color32.op_Implicit(Color.red);
				val.LabelSelectedColor = Color.red;
				val.LabelUnselectedColor = Color.red;
			}
			else
			{
				SimplePhoneButton obj = val;
				((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
				{
					MusicCuratorPlugin.SetAppShuffle(shuffling: true);
					MusicCuratorPlugin.shufflingPlaylist = true;
					MusicCuratorPlugin.queuedTracks.Clear();
					MusicCuratorPlugin.LoadPlaylistIntoQueue(MusicCuratorPlugin.selectedPlaylist, randomize: true);
					MusicCuratorPlugin.SkipCurrentTrack();
					((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
				});
			}
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Play and loop playlist");
			if (flag)
			{
				((TMP_Text)val.Label).faceColor = Color32.op_Implicit(Color.red);
				val.LabelSelectedColor = Color.red;
				val.LabelUnselectedColor = Color.red;
			}
			else
			{
				SimplePhoneButton obj2 = val;
				((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
				{
					MusicCuratorPlugin.SetAppShuffle(shuffling: false);
					MusicCuratorPlugin.shufflingPlaylist = false;
					MusicCuratorPlugin.queuedTracks.Clear();
					MusicCuratorPlugin.LoadPlaylistIntoQueue(MusicCuratorPlugin.selectedPlaylist);
					MusicCuratorPlugin.SkipCurrentTrack();
					((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
				});
			}
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Edit playlist");
			SimplePhoneButton obj3 = val;
			((PhoneButton)obj3).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj3).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppEditPlaylist));
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			if (!MusicCuratorPlugin.ListAInB(MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist], MusicCuratorPlugin.queuedTracks))
			{
				val = PhoneUIUtility.CreateSimpleButton("Add playlist to queue");
				if (flag)
				{
					((TMP_Text)val.Label).faceColor = Color32.op_Implicit(Color.red);
					val.LabelSelectedColor = Color.red;
					val.LabelUnselectedColor = Color.red;
				}
				else
				{
					SimplePhoneButton obj4 = val;
					((PhoneButton)obj4).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj4).OnConfirm, (Action)delegate
					{
						MusicCuratorPlugin.queuedTracks.AddRange(MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist]);
						((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
					});
				}
			}
			else
			{
				val = PhoneUIUtility.CreateSimpleButton("Remove playlist from queue");
				if (flag)
				{
					((TMP_Text)val.Label).faceColor = Color32.op_Implicit(Color.red);
					val.LabelSelectedColor = Color.red;
					val.LabelUnselectedColor = Color.red;
				}
				else
				{
					SimplePhoneButton obj5 = val;
					((PhoneButton)obj5).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj5).OnConfirm, (Action)delegate
					{
						MusicCuratorPlugin.queuedTracks = MusicCuratorPlugin.queuedTracks.Except(MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist]).ToList();
						((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
					});
				}
			}
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			if (!MusicCuratorPlugin.ListAInB(MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist], MusicCuratorPlugin.excludedTracks))
			{
				val = PhoneUIUtility.CreateSimpleButton("Add playlist to blocklist");
				SimplePhoneButton obj6 = val;
				((PhoneButton)obj6).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj6).OnConfirm, (Action)delegate
				{
					MusicCuratorPlugin.excludedTracks.AddRange(MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist]);
					if (MusicCuratorPlugin.currentPlaylistIndex == MusicCuratorPlugin.selectedPlaylist)
					{
						MusicCuratorPlugin.currentPlaylistIndex = -1;
						MusicCuratorPlugin.playlistTracks.Clear();
						MusicCuratorPlugin.SkipCurrentTrack();
					}
					MusicCuratorPlugin.SaveExclusions();
					((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
				});
			}
			else
			{
				val = PhoneUIUtility.CreateSimpleButton("Remove playlist from blocklist");
				SimplePhoneButton obj7 = val;
				((PhoneButton)obj7).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj7).OnConfirm, (Action)delegate
				{
					MusicCuratorPlugin.excludedTracks = MusicCuratorPlugin.excludedTracks.Except(MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist]).ToList();
					MusicCuratorPlugin.SaveExclusions();
					((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
				});
			}
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Delete playlist");
			SimplePhoneButton obj8 = val;
			((PhoneButton)obj8).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj8).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppDeletePlaylist));
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Cancel");
			SimplePhoneButton obj9 = val;
			((PhoneButton)obj9).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj9).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			((App)this).OnAppEnable();
		}

		public override void OnAppDisable()
		{
			((CustomApp)this).ScrollView.RemoveAllButtons();
			((App)this).OnAppDisable();
			Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}
	}
	public class AppEditPlaylist : TracksHeaderApp
	{
		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppEditPlaylist>("edit playlist", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			CreateAndSaveIconlessTitleBar("Edit " + MusicCuratorPlugin.GetPlaylistName(MusicCuratorPlugin.selectedPlaylist));
			MusicCuratorPlugin.ReorderPlaylistInQueue(MusicCuratorPlugin.musicPlayer.shuffle);
			SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton("Add tracks...");
			SimplePhoneButton obj = val;
			((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppPlaylistTracklist));
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Reorder tracks...");
			SimplePhoneButton obj2 = val;
			((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppReorderPlaylist));
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			foreach (MusicTrack mpTrack in MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist])
			{
				string text = mpTrack.Artist + " - " + mpTrack.Title;
				val = PhoneUIUtility.CreateSimpleButton(text);
				if (MusicCuratorPlugin.IsInvalidTrack(mpTrack))
				{
					((TMP_Text)val.Label).faceColor = Color32.op_Implicit(Color.red);
					val.LabelSelectedColor = Color.red;
					val.LabelUnselectedColor = Color.red;
				}
				SimplePhoneButton obj3 = val;
				((PhoneButton)obj3).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj3).OnConfirm, (Action)delegate
				{
					MusicCuratorPlugin.appSelectedTrack = MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].IndexOf(mpTrack);
					((App)this).MyPhone.OpenApp(typeof(AppRemoveTrackFromPlaylist));
				});
				((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			}
			((App)this).OnAppEnable();
			((CustomApp)this).ScrollView.ScrollUp();
		}

		public override void OnAppDisable()
		{
			((CustomApp)this).ScrollView.RemoveAllButtons();
			Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
			if (!MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Any())
			{
				MusicCuratorPlugin.selectedPlaylist = -1;
			}
		}

		public override void OnReleaseLeft()
		{
			if (!MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Any())
			{
				MusicCuratorPlugin.selectedPlaylist = -1;
				((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
			}
			else
			{
				((App)this).OnReleaseLeft();
			}
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}
	}
	public class AppRemoveTrackFromPlaylist : TracksHeaderApp
	{
		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppRemoveTrackFromPlaylist>("remove from playlist", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			CreateAndSaveIconlessTitleBar("Edit " + MusicCuratorPlugin.GetPlaylistName(MusicCuratorPlugin.selectedPlaylist));
			MusicTrack val = MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist][MusicCuratorPlugin.appSelectedTrack];
			SimplePhoneButton val2 = PhoneUIUtility.CreateSimpleButton("Remove track " + val.Title + " from playlist");
			SimplePhoneButton obj = val2;
			((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
			{
				MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].RemoveAt(MusicCuratorPlugin.appSelectedTrack);
				MusicCuratorPlugin.appSelectedTrack = -1;
				if (!MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Any())
				{
					MusicCuratorPlugin.selectedPlaylist = -1;
					((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
				}
				else
				{
					MusicCuratorPlugin.ReorderPlaylistInQueue(MusicCuratorPlugin.musicPlayer.shuffle);
					((App)this).MyPhone.OpenApp(typeof(AppEditPlaylist));
					((App)this).MyPhone.m_PreviousApps.Pop();
					((App)this).MyPhone.m_PreviousApps.Pop();
				}
				MusicCuratorPlugin.SavePlaylists();
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val2);
			val2 = PhoneUIUtility.CreateSimpleButton("Cancel");
			SimplePhoneButton obj2 = val2;
			((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
			{
				MusicCuratorPlugin.appSelectedTrack = -1;
				((App)this).MyPhone.OpenApp(typeof(AppEditPlaylist));
				((App)this).MyPhone.m_PreviousApps.Pop();
				((App)this).MyPhone.m_PreviousApps.Pop();
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val2);
			((App)this).OnAppEnable();
		}

		public override void OnAppDisable()
		{
			((CustomApp)this).ScrollView.RemoveAllButtons();
			Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
			((App)this).OnAppDisable();
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}
	}
	public class AppPlaylistTracklist : CustomApp
	{
		public static List<MusicTrack> selectedTracksToAddToPlaylist = new List<MusicTrack>();

		public static Color LabelSelectedColorDefault = Color32.op_Implicit(new Color32((byte)49, (byte)90, (byte)165, byte.MaxValue));

		public static Color LabelUnselectedColorDefault = Color.white;

		public static bool creatingPlaylist = false;

		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppPlaylistTracklist>("playlist tracklist", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			foreach (MusicTrack mpTrack in MusicCuratorPlugin.GetAllMusic())
			{
				if (MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Contains(mpTrack))
				{
					continue;
				}
				MusicCuratorPlugin.Log.LogInfo((object)("Tracklist App: Adding " + mpTrack.Artist + " - " + mpTrack.Title));
				SimplePhoneButton nextButton = PhoneUIUtility.CreateSimpleButton(mpTrack.Artist + " - " + mpTrack.Title);
				SimplePhoneButton obj = nextButton;
				((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
				{
					//IL_0091: Unknown result type (might be due to invalid IL or missing references)
					//IL_0096: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
					//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
					//IL_003c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0041: Unknown result type (might be due to invalid IL or missing references)
					//IL_0052: Unknown result type (might be due to invalid IL or missing references)
					//IL_0057: Unknown result type (might be due to invalid IL or missing references)
					//IL_0062: Unknown result type (might be due to invalid IL or missing references)
					//IL_0067: Unknown result type (might be due to invalid IL or missing references)
					if (selectedTracksToAddToPlaylist.Contains(mpTrack))
					{
						selectedTracksToAddToPlaylist.Remove(mpTrack);
						((TMP_Text)nextButton.Label).faceColor = Color32.op_Implicit(LabelSelectedColorDefault);
						nextButton.LabelSelectedColor = LabelSelectedColorDefault;
						nextButton.LabelUnselectedColor = LabelUnselectedColorDefault;
					}
					else
					{
						selectedTracksToAddToPlaylist.Add(mpTrack);
						((TMP_Text)nextButton.Label).faceColor = Color32.op_Implicit(Color.green);
						nextButton.LabelSelectedColor = Color.green;
						nextButton.LabelUnselectedColor = Color.green;
					}
				});
				base.ScrollView.AddButton((PhoneButton)(object)nextButton);
			}
			selectedTracksToAddToPlaylist.Clear();
			((App)this).OnAppEnable();
			base.ScrollView.ScrollUp();
		}

		public override void OnAppDisable()
		{
			creatingPlaylist = false;
			base.ScrollView.RemoveAllButtons();
			selectedTracksToAddToPlaylist.Clear();
			((App)this).OnAppDisable();
		}

		public override void OnReleaseLeft()
		{
			foreach (MusicTrack item in selectedTracksToAddToPlaylist)
			{
				MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Add(item);
			}
			selectedTracksToAddToPlaylist.Clear();
			MusicCuratorPlugin.SavePlaylists();
			MusicCuratorPlugin.ReorderPlaylistInQueue(MusicCuratorPlugin.musicPlayer.shuffle);
			if (creatingPlaylist)
			{
				creatingPlaylist = false;
				((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
			}
			else
			{
				((App)this).OnReleaseLeft();
			}
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).CreateIconlessTitleBar("Tracklist", 80f);
			base.ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}
	}
	public class AppDeletePlaylist : TracksHeaderApp
	{
		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppDeletePlaylist>("delete playlist", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			CreateAndSaveIconlessTitleBar("Delete " + MusicCuratorPlugin.GetPlaylistName(MusicCuratorPlugin.selectedPlaylist));
			SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton("Cancel");
			SimplePhoneButton obj = val;
			((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppSelectedPlaylist));
				((App)this).MyPhone.m_PreviousApps.Pop();
				((App)this).MyPhone.m_PreviousApps.Pop();
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Delete playlist (permanent!)");
			((TMP_Text)val.Label).faceColor = Color32.op_Implicit(Color.red);
			val.LabelSelectedColor = Color.red;
			val.LabelUnselectedColor = Color.red;
			SimplePhoneButton obj2 = val;
			((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
			{
				if (MusicCuratorPlugin.currentPlaylistIndex == MusicCuratorPlugin.selectedPlaylist)
				{
					MusicCuratorPlugin.playlistTracks.Clear();
					MusicCuratorPlugin.currentPlaylistIndex = -1;
				}
				MusicCuratorPlugin.playlists.RemoveAt(MusicCuratorPlugin.selectedPlaylist);
				MusicCuratorPlugin.selectedPlaylist = -1;
				MusicCuratorPlugin.appSelectedTrack = -1;
				MusicCuratorPlugin.SavePlaylists();
				((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
				((App)this).MyPhone.m_PreviousApps.Pop();
				((App)this).MyPhone.m_PreviousApps.Pop();
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			((App)this).OnAppEnable();
		}

		public override void OnAppDisable()
		{
			((CustomApp)this).ScrollView.RemoveAllButtons();
			Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
			((App)this).OnAppDisable();
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}
	}
	public class AppDeleteAllPlaylists : TracksHeaderApp
	{
		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppDeleteAllPlaylists>("delete all playlist", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			CreateAndSaveIconlessTitleBar("Are you sure?");
			SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton("Cancel");
			SimplePhoneButton obj = val;
			((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
			{
				((App)this).MyPhone.OpenApp(typeof(AppManageQueueAndExclusions));
				((App)this).MyPhone.m_PreviousApps.Pop();
				((App)this).MyPhone.m_PreviousApps.Pop();
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			val = PhoneUIUtility.CreateSimpleButton("Delete all playlists (permanent!)");
			((TMP_Text)val.Label).faceColor = Color32.op_Implicit(Color.red);
			val.LabelSelectedColor = Color.red;
			val.LabelUnselectedColor = Color.red;
			SimplePhoneButton obj2 = val;
			((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
			{
				MusicCuratorPlugin.playlists.Clear();
				PlaylistSaveData.playlists.Clear();
				MusicCuratorPlugin.currentPlaylistIndex = -1;
				MusicCuratorPlugin.SavePlaylists();
				((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			((App)this).OnAppEnable();
		}

		public override void OnAppDisable()
		{
			((CustomApp)this).ScrollView.RemoveAllButtons();
			Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
			((App)this).OnAppDisable();
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}
	}
	public class AppReorderPlaylist : TracksHeaderApp
	{
		public static bool draggingTrack;

		private static SimplePhoneButton selectedButton;

		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppReorderPlaylist>("reorder playlist", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			CreateAndSaveIconlessTitleBar("Edit " + MusicCuratorPlugin.GetPlaylistName(MusicCuratorPlugin.selectedPlaylist));
			foreach (MusicTrack item2 in MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist])
			{
				string text = item2.Artist + " - " + item2.Title;
				SimplePhoneButton nextButton = PhoneUIUtility.CreateSimpleButton(text);
				if (MusicCuratorPlugin.IsInvalidTrack(item2))
				{
					((TMP_Text)nextButton.Label).faceColor = Color32.op_Implicit(Color.red);
					nextButton.LabelSelectedColor = Color.red;
					nextButton.LabelUnselectedColor = Color.red;
				}
				SimplePhoneButton obj = nextButton;
				((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
				{
					//IL_0144: Unknown result type (might be due to invalid IL or missing references)
					//IL_0149: Unknown result type (might be due to invalid IL or missing references)
					//IL_015a: Unknown result type (might be due to invalid IL or missing references)
					//IL_015f: Unknown result type (might be due to invalid IL or missing references)
					//IL_016a: Unknown result type (might be due to invalid IL or missing references)
					//IL_016f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0055: Unknown result type (might be due to invalid IL or missing references)
					//IL_005a: Unknown result type (might be due to invalid IL or missing references)
					//IL_006a: Unknown result type (might be due to invalid IL or missing references)
					//IL_006f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0079: Unknown result type (might be due to invalid IL or missing references)
					//IL_007e: Unknown result type (might be due to invalid IL or missing references)
					if (draggingTrack)
					{
						draggingTrack = false;
						int num = ((CustomApp)this).ScrollView.Buttons.IndexOf((PhoneButton)(object)nextButton);
						int num2 = ((CustomApp)this).ScrollView.Buttons.IndexOf((PhoneButton)(object)selectedButton);
						((TMP_Text)selectedButton.Label).faceColor = Color32.op_Implicit(AppPlaylistTracklist.LabelSelectedColorDefault);
						selectedButton.LabelSelectedColor = AppPlaylistTracklist.LabelSelectedColorDefault;
						selectedButton.LabelUnselectedColor = AppPlaylistTracklist.LabelUnselectedColorDefault;
						if (num != num2)
						{
							((CustomApp)this).ScrollView.Buttons.RemoveAt(num2);
							((CustomApp)this).ScrollView.InsertButton(num, (PhoneButton)(object)selectedButton);
							((CustomApp)this).ScrollView.UpdateButtons();
							((PhoneButton)nextButton).PlayDeselectAnimation(false);
							MusicTrack item = MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist][num2];
							MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].RemoveAt(num2);
							MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Insert(num, item);
						}
					}
					else
					{
						draggingTrack = true;
						selectedButton = nextButton;
						((TMP_Text)nextButton.Label).faceColor = Color32.op_Implicit(Color.green);
						nextButton.LabelSelectedColor = Color.green;
						nextButton.LabelUnselectedColor = Color.green;
					}
				});
				((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)nextButton);
			}
			((App)this).OnAppEnable();
			((CustomApp)this).ScrollView.ScrollUp();
		}

		public override void OnAppDisable()
		{
			((CustomApp)this).ScrollView.RemoveAllButtons();
			Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
			draggingTrack = false;
			if (!MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Any())
			{
				MusicCuratorPlugin.selectedPlaylist = -1;
			}
		}

		public override void OnReleaseLeft()
		{
			if (!MusicCuratorPlugin.playlists[MusicCuratorPlugin.selectedPlaylist].Any())
			{
				MusicCuratorPlugin.selectedPlaylist = -1;
				((App)this).MyPhone.OpenApp(typeof(AppPlaylists));
			}
			else
			{
				((App)this).OnReleaseLeft();
			}
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}
	}
	[BepInPlugin("goatgirl.MusicCurator", "MusicCurator", "0.1.0")]
	[BepInProcess("Bomb Rush Cyberfunk.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class MusicCuratorPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static Harmony Harmony = new Harmony("goatgirl.MusicCurator");

		public static Random rando = new Random();

		public static List<MusicTrack> excludedTracks = new List<MusicTrack>();

		public static List<MusicTrack> queuedTracks = new List<MusicTrack>();

		public static List<List<MusicTrack>> playlists = new List<List<MusicTrack>>();

		public static List<MusicTrack> playlistTracks = new List<MusicTrack>();

		public static int currentPlaylistIndex = -1;

		public static bool shufflingPlaylist = false;

		public static MusicTrack playlistStartingTrack;

		public static bool skipping = false;

		public static bool ContinuingStageTrack = false;

		public static bool hasInstantShuffledAlready = false;

		public static int selectedPlaylist = -1;

		public static int appSelectedTrack = -1;

		public static Sprite loopingSingleTrackSprite = null;

		public static int loopingSingleTrackIndex = -1;

		public static bool hasShuffleify = false;

		public static bool hasBRR = false;

		public static MusicTrack missingStageTrack = null;

		public static int pausePlaybackSamples = 0;

		public static int pausedTrack;

		public const string songIDSymbol = "♫";

		public static MusicCuratorPlugin Instance { get; private set; }

		public string Directory => Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);

		public static MusicPlayer musicPlayer
		{
			get
			{
				IMusicPlayer obj = Core.Instance.AudioManager.MusicPlayer;
				return (MusicPlayer)(object)((obj is MusicPlayer) ? obj : null);
			}
		}

		public static Player player
		{
			get
			{
				WorldHandler instance = WorldHandler.instance;
				return (instance != null) ? instance.GetCurrentPlayer() : null;
			}
		}

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin MusicCurator is loaded!");
			MCSettings.BindSettings(((BaseUnityPlugin)this).Config);
			MCSettings.UpdateSettings();
			new PlaylistSaveData();
			AppPlaylists.Initialize();
			AppNewPlaylist.Initialize();
			AppPlaylistTracklist.Initialize();
			AppSelectedPlaylist.Initialize();
			AppEditPlaylist.Initialize();
			AppReorderPlaylist.Initialize();
			AppRemoveTrackFromPlaylist.Initialize();
			AppDeletePlaylist.Initialize();
			AppManageQueueAndExclusions.Initialize();
			AppDeleteAllPlaylists.Initialize();
			loopingSingleTrackSprite = TextureUtility.LoadSprite(Path.Combine(Instance.Directory, "MC-LoopSingle.png"));
			((Texture)loopingSingleTrackSprite.texture).filterMode = (FilterMode)0;
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				if (pluginInfo.Value.Metadata.GUID.Contains("BombRushRadio"))
				{
					hasBRR = true;
					Log.LogInfo((object)"BombRushRadio install detected!");
				}
				if (pluginInfo.Value.Metadata.GUID.Equals("com.dragsun.Shuffleify") || pluginInfo.Value.Metadata.GUID.Equals("com.dragsun.Shufleify"))
				{
					hasShuffleify = true;
					Log.LogError((object)"Shuffleify install detected!");
					Log.LogError((object)"Shuffleify patches much of the same code that MusicCurator patches, and implements many of the same features (startup shuffle, looping single songs, etc.)");
					Log.LogError((object)"Running both Shuffleify and MusicCurator can and likely will lead to issues with both plugins!");
					Log.LogError((object)"Considering the significant amount of feature overlap, I highly recommend uninstalling either Shuffleify or MusicCurator.");
				}
			}
		}

		public static void resetVariables()
		{
			excludedTracks = new List<MusicTrack>();
			queuedTracks = new List<MusicTrack>();
			playlists = new List<List<MusicTrack>>();
			playlistTracks = new List<MusicTrack>();
			currentPlaylistIndex = -1;
			shufflingPlaylist = false;
			playlistStartingTrack = null;
			skipping = false;
			ContinuingStageTrack = false;
			hasInstantShuffledAlready = false;
			selectedPlaylist = -1;
			appSelectedTrack = -1;
			loopingSingleTrackIndex = -1;
			missingStageTrack = null;
			pausePlaybackSamples = 0;
			pausedTrack = 0;
		}

		private void OnDestroy()
		{
			Harmony.UnpatchSelf();
		}

		private void Update()
		{
			if (pressedAnyButtonIn(MCSettings.keybindsPause))
			{
				if (musicPlayer.IsPlaying)
				{
					pausePlaybackSamples = musicPlayer.CurrentTrackSamples;
					pausedTrack = musicPlayer.CurrentTrackIndex;
					musicPlayer.Pause();
				}
				else
				{
					musicPlayer.Play();
					if (musicPlayer.CurrentTrackIndex == pausedTrack)
					{
						musicPlayer.playbackSamples = pausePlaybackSamples;
					}
				}
			}
			if (PlayerUsingMusicApp())
			{
				App obj = player.phone.AppInstances["AppMusicPlayer"];
				PhoneScrollButton selectedButtton = ((PhoneScroll)((AppMusicPlayer)((obj is AppMusicPlayer) ? obj : null)).m_TrackList).SelectedButtton;
				MusicPlayerTrackButton val = (MusicPlayerTrackButton)(object)((selectedButtton is MusicPlayerTrackButton) ? selectedButtton : null);
				AUnlockable assignedContent = ((PhoneScrollUnlockableButton)val).AssignedContent;
				MusicTrack item = (MusicTrack)(object)((assignedContent is MusicTrack) ? assignedContent : null);
				if (pressedAnyButtonIn(MCSettings.keybindsShuffle))
				{
					SetAppShuffle(!musicPlayer.shuffle);
				}
				if (pressedAnyButtonIn(MCSettings.keybindsSkip))
				{
					if (!excludedTracks.Contains(item))
					{
						excludedTracks.Add(item);
						if (val.IsMyTrackPlaying())
						{
							SkipCurrentTrack();
						}
						CheckIfAllExcluded();
						SaveExclusions();
					}
					else
					{
						excludedTracks.Remove(item);
					}
				}
				else if (pressedAnyButtonIn(MCSettings.keybindsQueue))
				{
					if (!queuedTracks.Contains(item))
					{
						queuedTracks.Add(item);
					}
					else
					{
						queuedTracks.Remove(item);
					}
				}
			}
			else if (pressedAnyButtonIn(MCSettings.keybindsSkip))
			{
				SkipCurrentTrack();
			}
		}

		public static void SkipCurrentTrack()
		{
			skipping = true;
			musicPlayer.ForcePaused();
			musicPlayer.PlayNext();
			skipping = false;
		}

		public static void UpdateButtonColor(MusicPlayerTrackButton button)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			AUnlockable assignedContent = ((PhoneScrollUnlockableButton)button).AssignedContent;
			MusicTrack val = (MusicTrack)(object)((assignedContent is MusicTrack) ? assignedContent : null);
			TextMeshProUGUI val2 = ((Component)button.m_TitleLabel).GetComponentsInChildren<TextMeshProUGUI>().LastOrDefault();
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)button.m_TitleLabel)
			{
				if (((TMP_Text)val2).text == "")
				{
					((TMP_Text)val2).outlineWidth = 0.4f;
					((TMP_Text)val2).outlineColor = Color32.op_Implicit(button.m_ArtistColorNormal);
					((TMP_Text)val2).fontSharedMaterial.SetFloat(ShaderUtilities.ID_FaceDilate, 0.4f);
				}
				if (playlistTracks.Contains(val) && !button.IsMyTrackPlaying())
				{
					((TMP_Text)val2).text = (playlistTracks.IndexOf(val) + 1 + queuedTracks.Count).ToString();
				}
				else
				{
					((TMP_Text)val2).text = (queuedTracks.IndexOf(val) + 1).ToString();
					if (playlistTracks.Any() && currentPlaylistIndex >= 0 && ((TMP_Text)val2).text != "0")
					{
						((TMP_Text)val2).text = ((TMP_Text)val2).text + "*";
					}
				}
				if (((TMP_Text)val2).text == "0")
				{
					((TMP_Text)val2).text = "   ";
				}
			}
			if (!(val.Title != ((TMP_Text)button.m_TitleLabel).text) && !((PhoneScrollButton)button).IsHidden)
			{
				if (excludedTracks.Contains(val))
				{
					((Graphic)button.m_TitleLabel).color = Color.red;
					((Graphic)button.m_ArtistLabel).color = Color.red;
				}
				else if (((PhoneScrollButton)button).IsSelected)
				{
					((Graphic)button.m_TitleLabel).color = button.m_TitleColorSelected;
					((Graphic)button.m_ArtistLabel).color = button.m_ArtistColorSelected;
				}
				else
				{
					((Graphic)button.m_TitleLabel).color = button.m_TitleColorNormal;
					((Graphic)button.m_ArtistLabel).color = button.m_ArtistColorNormal;
				}
			}
		}

		public static void PlayTrack(MusicTrack targetTrack, int playbackSamples = 0)
		{
			int num = musicPlayer.musicTrackQueue.currentMusicTracks.IndexOf(targetTrack);
			if (num == -1 || num >= GetAllMusic().Count)
			{
				Log.LogError((object)"(MusicCuratorPlugin.PlayTrack) Target track outside range!");
				return;
			}
			musicPlayer.ForcePaused();
			ContinuingStageTrack = true;
			musicPlayer.PlayFrom(num, playbackSamples);
			ContinuingStageTrack = false;
		}

		public static void SetAppShuffle(bool shuffling)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player.phone == (Object)null))
			{
				player.phone.GetAppInstance<AppMusicPlayer>().ToggleShuffle(shuffling);
			}
		}

		public static void LoadPlaylistIntoQueue(int playlistIndex, bool randomize = false)
		{
			if (playlistIndex < 0 || playlistIndex > playlists.Count)
			{
				Log.LogError((object)("Playlist " + playlistIndex + " outside range!"));
				return;
			}
			playlistTracks.Clear();
			foreach (MusicTrack item in playlists[playlistIndex])
			{
				if (!IsInvalidTrack(item))
				{
					playlistTracks.Add(item);
				}
			}
			if (!playlistTracks.Any())
			{
				Log.LogError((object)("Playlist " + playlistIndex + " entirely invalid/blank! Not playing it!"));
				return;
			}
			currentPlaylistIndex = playlistIndex;
			if (randomize)
			{
				playlistTracks = RandomizeList(playlistTracks);
			}
			playlistStartingTrack = playlistTracks.LastOrDefault();
		}

		public static void ReorderPlaylistInQueue(bool randomize, bool seekToCurrentTrack = true)
		{
			if (currentPlaylistIndex == -1 || currentPlaylistIndex >= playlists.Count)
			{
				return;
			}
			MusicTrack currentMusicTrack = musicPlayer.musicTrackQueue.CurrentMusicTrack;
			List<MusicTrack> list = new List<MusicTrack>();
			foreach (MusicTrack item in playlists[currentPlaylistIndex].ToList())
			{
				if (!IsInvalidTrack(item))
				{
					list.Add(item);
				}
			}
			if (randomize)
			{
				list = RandomizeList(list);
			}
			playlistTracks = list;
			if (!seekToCurrentTrack)
			{
				return;
			}
			foreach (MusicTrack item2 in list.ToList())
			{
				playlistTracks.RemoveAt(0);
				playlistTracks.Add(item2);
				if ((Object)(object)item2 == (Object)(object)currentMusicTrack)
				{
					break;
				}
			}
		}

		public static void ClearEmptyPlaylists(bool save = true)
		{
			int[] array = Enumerable.Range(0, playlists.Count).ToArray();
			foreach (int num in array)
			{
				if (playlists.ElementAtOrDefault(num) != null && !playlists[num].Any())
				{
					playlists.RemoveAt(num);
					if (currentPlaylistIndex == num)
					{
						playlistTracks.Clear();
						currentPlaylistIndex = -1;
					}
				}
			}
			if (save)
			{
				SavePlaylists(skipClear: true);
			}
		}

		public static List<MusicTrack> GetAllMusic()
		{
			return musicPlayer.musicTrackQueue.currentMusicTracks;
		}

		public static int CreatePlaylist()
		{
			playlists.Add(new List<MusicTrack>());
			SavePlaylists(skipClear: true);
			return playlists.Count - 1;
		}

		public static List<T> RandomizeList<T>(List<T> listToRandomize)
		{
			if (listToRandomize.Count <= 1)
			{
				return listToRandomize;
			}
			int num = listToRandomize.Count;
			while (num > 1)
			{
				num--;
				int index = rando.Next(num + 1);
				T value = listToRandomize[index];
				listToRandomize[index] = listToRandomize[num];
				listToRandomize[num] = value;
			}
			return listToRandomize;
		}

		public static bool PlayerUsingMusicApp()
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player.phone == (Object)null)
			{
				return false;
			}
			return player.phone.m_CurrentApp is AppMusicPlayer && player.phone.IsOn && player.phoneLayerWeight >= 1f;
		}

		public static string GetPlaylistName(int playlistIndex)
		{
			if (playlistIndex < 0 || playlistIndex >= MCSettings.customPlaylistNames.Count)
			{
				return "New Playlist " + (playlistIndex + 1);
			}
			return MCSettings.customPlaylistNames[playlistIndex].Substring(0, Math.Min(MCSettings.customPlaylistNames[playlistIndex].Length, 32));
		}

		public static bool ListAInB<T>(List<T> listA, List<T> listB)
		{
			return !listA.Except(listB).Any();
		}

		public static bool IsInvalidTrack(MusicTrack checkTrack)
		{
			return (checkTrack.Title == string.Empty && checkTrack.Artist == string.Empty) || (Object)(object)checkTrack.AudioClip == (Object)null;
		}

		public static bool pressedAnyButtonIn(List<KeyCode> keybinds)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyCode keybind in keybinds)
			{
				if (Input.GetKeyUp(keybind))
				{
					return true;
				}
			}
			return false;
		}

		public static MusicTrack FindTrackBySongID(string songID)
		{
			List<MusicTrack> list = new List<MusicTrack>();
			foreach (MusicTrack item in GetAllMusic())
			{
				if (TrackToSongID(item).Equals(ConformSongID(songID)))
				{
					list.Add(item);
				}
			}
			if (list.Count < 1)
			{
				Log.LogWarning((object)$"FindTrackBySongID: Track {songID} not found. Creating empty track to prevent crashes");
				return CreateDummyTrack(songID);
			}
			if (list.Count > 1)
			{
				Log.LogError((object)$"FindTrackBySongID: Multiple tracks are sharing songID {songID} (same name and artist)! Please make sure your custom songs all have unique names/artists!!! First track found using songID will be returned - this may not be what you want!");
			}
			return list[0];
		}

		public static MusicTrack LooseFindTrackBySongID(string songID)
		{
			List<MusicTrack> list = new List<MusicTrack>();
			string[] array = SplitSongID(songID);
			string text = array[1].Trim();
			int num = 999;
			foreach (MusicTrack item in GetAllMusic())
			{
				string text2 = TrackToSongID(item);
				if (text2.Contains(ConformSongID(songID)))
				{
					list.Add(item);
					int num2 = Mathf.Abs(text2.Length - songID.Length);
					if (num2 < num)
					{
						num = num2;
					}
				}
			}
			foreach (MusicTrack item2 in list)
			{
				if (Mathf.Abs(TrackToSongID(item2).Length - songID.Length) == num)
				{
					return item2;
				}
			}
			list.Clear();
			num = 999;
			foreach (MusicTrack item3 in GetAllMusic())
			{
				string text3 = TrackToSongID(item3);
				if (text3.Contains(text))
				{
					list.Add(item3);
					int num3 = Mathf.Abs(item3.Title.Length - text.Length);
					if (num3 < num)
					{
						num = num3;
					}
				}
			}
			foreach (MusicTrack item4 in list)
			{
				if (Mathf.Abs(item4.Title.Length - text.Length) == num)
				{
					return item4;
				}
			}
			return CreateDummyTrack(songID);
		}

		public static MusicTrack CreateDummyTrack(string songID)
		{
			MusicTrack val = ScriptableObject.CreateInstance<MusicTrack>();
			string[] array = SplitSongID(songID);
			val.AudioClip = null;
			val.Artist = array[0].Trim();
			val.Title = array[1].Trim();
			return val;
		}

		public static string TrackToSongID(MusicTrack startingTrack)
		{
			return ConformSongID(startingTrack.Artist + "♫" + startingTrack.Title);
		}

		public static string ConformSongID(string ogID)
		{
			return ogID.Replace(" ♫ ", "♫").ToLower().Trim();
		}

		public static string[] SplitSongID(string songID, string splitSymbol = "♫")
		{
			string[] array = songID.Split(new string[1] { "♫" }, StringSplitOptions.None);
			if (array.Length > 2)
			{
				Log.LogError((object)("SplitSongID: SongID \"" + songID + "\" using illegal symbol \"" + splitSymbol + "\" in either title or artist! Please remove this symbol from this track's title/artist. This track cannot be safely added to playlists or blocklists."));
			}
			return array;
		}

		public static void LoadPlaylists(List<List<string>> playlistsBySongID)
		{
			playlists.Clear();
			foreach (List<string> item in playlistsBySongID)
			{
				List<MusicTrack> list = new List<MusicTrack>();
				foreach (string item2 in item)
				{
					list.Add(FindTrackBySongID(item2));
				}
				playlists.Add(list);
			}
			LoadExclusions();
			((CustomSaveData)PlaylistSaveData.Instance).AutoSave = true;
		}

		public static void LoadExclusions(bool skipCheck = false)
		{
			excludedTracks.Clear();
			foreach (string item in PlaylistSaveData.excludedTracksCarryOver)
			{
				if (!IsInvalidTrack(FindTrackBySongID(item)))
				{
					excludedTracks.Add(FindTrackBySongID(item));
				}
			}
			if (!skipCheck)
			{
				CheckIfAllExcluded();
			}
		}

		public static void SavePlaylists(bool skipClear = false)
		{
			if (!skipClear)
			{
				ClearEmptyPlaylists(save: false);
				ClearDupes_P();
			}
			PlaylistSaveData.playlists.Clear();
			foreach (List<MusicTrack> playlist in playlists)
			{
				List<string> list = new List<string>();
				foreach (MusicTrack item in playlist)
				{
					list.Add(TrackToSongID(item));
				}
				PlaylistSaveData.playlists.Add(list);
			}
			SaveExclusions();
		}

		public static void SaveExclusions()
		{
			PlaylistSaveData.excludedTracksCarryOver = PlaylistSaveData.defaultExclusions;
			foreach (MusicTrack excludedTrack in excludedTracks)
			{
				if (!PlaylistSaveData.excludedTracksCarryOver.Contains(TrackToSongID(excludedTrack)))
				{
					PlaylistSaveData.excludedTracksCarryOver.Add(TrackToSongID(excludedTrack));
				}
			}
			ClearDupes_E();
		}

		public static void ClearDupes_P()
		{
			int num = -1;
			foreach (List<MusicTrack> item in playlists.ToList())
			{
				num++;
				playlists[num] = item.Distinct().ToList();
				PlaylistSaveData.playlists[num] = PlaylistSaveData.playlists[num].Distinct().ToList();
			}
		}

		public static void ClearDupes_E()
		{
			excludedTracks = excludedTracks.Distinct().ToList();
			PlaylistSaveData.excludedTracksCarryOver = PlaylistSaveData.excludedTracksCarryOver.Distinct().ToList();
		}

		public static bool PlaylistAllInvalidTracks(int playlistIndex)
		{
			if (playlistIndex < 0 || playlistIndex > playlists.Count)
			{
				Log.LogError((object)("Playlist " + playlistIndex + " outside range!"));
				return false;
			}
			List<MusicTrack> list = playlists[playlistIndex];
			foreach (MusicTrack item in list)
			{
				if (!IsInvalidTrack(item))
				{
					return false;
				}
			}
			return true;
		}

		public static bool PlaylistAllExcludedTracks(int playlistIndex)
		{
			if (playlistIndex < 0 || playlistIndex > playlists.Count)
			{
				Log.LogError((object)("Playlist " + playlistIndex + " outside range!"));
				return false;
			}
			List<MusicTrack> list = playlists[playlistIndex];
			foreach (MusicTrack item in list)
			{
				if (!excludedTracks.Contains(item))
				{
					return false;
				}
			}
			return true;
		}

		public static bool PlaylistAnyInvalidTracks(int playlistIndex)
		{
			if (playlistIndex < 0 || playlistIndex > playlists.Count)
			{
				Log.LogError((object)("Playlist " + playlistIndex + " outside range!"));
				return false;
			}
			List<MusicTrack> list = playlists[playlistIndex];
			foreach (MusicTrack item in list)
			{
				if (IsInvalidTrack(item))
				{
					return true;
				}
			}
			return false;
		}

		public static void CheckIfAllExcluded()
		{
			if (!GetAllMusic().Any() || !excludedTracks.Any())
			{
				return;
			}
			foreach (MusicTrack item in GetAllMusic())
			{
				if (!excludedTracks.Contains(item))
				{
					return;
				}
			}
			Log.LogError((object)"Attempted to blocklist literally every track! Why??? Blocklist cleared");
			excludedTracks.Clear();
			PlaylistSaveData.excludedTracksCarryOver = PlaylistSaveData.defaultExclusions;
			LoadExclusions(skipCheck: true);
		}
	}
	public class PlaylistSaveData : CustomSaveData
	{
		public static List<List<string>> playlists = new List<List<string>>();

		public static List<string> excludedTracksCarryOver = new List<string>();

		public static readonly int saveVersion = 1;

		private static int readSaveVersion = 0;

		public static PlaylistSaveData Instance { get; private set; }

		public static List<string> defaultExclusions => MCSettings.alwaysSkipMixtapes.Value ? new List<string> { "tryce♫beats for the hideout", "dj cyber♫locking up the funk mixtape", "dj cyber♫house cats mixtape", "dj cyber♫beastmode hip hop mixtape", "dj cyber♫breaking machine mixtape", "dj cyber♫sunshine popping mixtape" } : new List<string>();

		public PlaylistSaveData()
			: base("MusicCurator", "Playlists.Slot{0}.data", (SaveLocations)2)
		{
			Instance = this;
			base.AutoSave = false;
		}

		public override void Initialize()
		{
			playlists.Clear();
			excludedTracksCarryOver = defaultExclusions;
		}

		public override void Read(BinaryReader reader)
		{
			playlists.Clear();
			excludedTracksCarryOver.Clear();
			MusicCuratorPlugin.playlists.Clear();
			MusicCuratorPlugin.excludedTracks.Clear();
			readSaveVersion = reader.ReadByte();
			int num = reader.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				int num2 = reader.ReadInt32();
				int num3 = reader.ReadInt32();
				List<string> list = new List<string>();
				for (int j = 0; j < num3; j++)
				{
					int num4 = reader.ReadInt32();
					string text = reader.ReadString();
					if (readSaveVersion == 0)
					{
						text = text.Replace("-", "♫");
					}
					list.Add(text);
				}
				playlists.Add(list);
			}
			int num5 = reader.ReadInt32();
			for (int k = 0; k < num5; k++)
			{
				int num6 = reader.ReadInt32();
				string text2 = reader.ReadString();
				if (readSaveVersion == 0)
				{
					text2 = text2.Replace("-", "♫");
				}
				excludedTracksCarryOver.Add(text2);
			}
		}

		public override void Write(BinaryWriter writer)
		{
			writer.Write((byte)saveVersion);
			writer.Write(playlists.Count);
			int num = -1;
			foreach (List<string> playlist in playlists)
			{
				num++;
				int num2 = -1;
				writer.Write(num);
				writer.Write(playlist.Count);
				foreach (string item in playlist)
				{
					num2++;
					writer.Write(num2);
					writer.Write(MusicCuratorPlugin.ConformSongID(item));
				}
			}
			writer.Write(excludedTracksCarryOver.Count);
			num = -1;
			foreach (string item2 in excludedTracksCarryOver)
			{
				num++;
				writer.Write(num);
				writer.Write(MusicCuratorPlugin.ConformSongID(item2));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "MusicCurator";

		public const string PLUGIN_NAME = "MusicCurator";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}