<commit_before>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using DataTool.ConvertLogic.WEM;
using DataTool.Helper;
using Newtonsoft.Json;
using TankLib;
using TankLib.Chunks;
using TankLib.STU;
using TankLib.STU.Types;
using static DataTool.Helper.STUHelper;
using static DataTool.Helper.IO;

namespace DataTool.FindLogic {
    public static class Combo {
        private static readonly HashSet<ushort> s_unhandledTypes = new HashSet<ushort>();

        public class ComboInfo {
            // keep everything at top level, stops us from doing the same things again.
            // everything here is unsorted, but we can use GUIDs as references.
            public Dictionary<ulong, EntityAsset> m_entities;
            public Dictionary<ulong, HashSet<ulong>> m_entitiesByIdentifier;
            public Dictionary<ulong, ModelAsset> m_models;
            public Dictionary<ulong, MaterialAsset> m_materials;
            public Dictionary<ulong, MaterialDataAsset> m_materialData;
            public Dictionary<ulong, ModelLookAsset> m_modelLooks;
            public Dictionary<ulong, AnimationAsset> m_animations;
            public Dictionary<ulong, TextureAsset> m_textures;
            public Dictionary<ulong, EffectInfoCombo> m_effects;
            public Dictionary<ulong, EffectInfoCombo> m_animationEffects;
            public Dictionary<ulong, SoundInfoNew> m_sounds;
            public Dictionary<ulong, WWiseBankInfo> m_soundBanks;
            public Dictionary<ulong, SoundFileAsset> m_voiceSoundFiles;
            public Dictionary<ulong, SoundFileAsset> m_soundFiles;
            public Dictionary<ulong, VoiceSetAsset> m_voiceSets;
            public Dictionary<ulong, DisplayTextAsset> m_displayText;
            public Dictionary<ulong, SubtitleAsset> m_subtitles;
            public HashSet<ulong> m_doneScripts;

            public bool m_processExistingEntities = false;
            public bool m_fullLog = false;

            public ComboInfo() {
                m_entities = new Dictionary<ulong, EntityAsset>();
                m_entitiesByIdentifier = new Dictionary<ulong, HashSet<ulong>>();
                m_models = new Dictionary<ulong, ModelAsset>();
                m_materials = new Dictionary<ulong, MaterialAsset>();
                m_materialData = new Dictionary<ulong, MaterialDataAsset>();
                m_modelLooks = new Dictionary<ulong, ModelLookAsset>();
                m_animations = new Dictionary<ulong, AnimationAsset>();
                m_textures = new Dictionary<ulong, TextureAsset>();
                m_effects = new Dictionary<ulong, EffectInfoCombo>();
                m_animationEffects = new Dictionary<ulong, EffectInfoCombo>();
                m_sounds = new Dictionary<ulong, SoundInfoNew>();
                m_soundBanks = new Dictionary<ulong, WWiseBankInfo>();
                m_voiceSoundFiles = new Dictionary<ulong, SoundFileAsset>();
                m_soundFiles = new Dictionary<ulong, SoundFileAsset>();
                m_voiceSets = new Dictionary<ulong, VoiceSetAsset>();
                m_displayText = new Dictionary<ulong, DisplayTextAsset>();
                m_subtitles = new Dictionary<ulong, SubtitleAsset>();
                m_doneScripts = new HashSet<ulong>();
            }

            public void RemoveByKey(ulong key) {
                m_entities.Remove(key);
                m_entitiesByIdentifier.Remove(key);
                m_models.Remove(key);
                m_materials.Remove(key);
                m_materialData.Remove(key);
                m_modelLooks.Remove(key);
                m_animations.Remove(key);
                m_textures.Remove(key);
                m_effects.Remove(key);
                m_animationEffects.Remove(key);
                m_sounds.Remove(key);
                m_soundBanks.Remove(key);
                m_voiceSoundFiles.Remove(key);
                m_soundFiles.Remove(key);
                m_voiceSets.Remove(key);
                m_displayText.Remove(key);
                m_subtitles.Remove(key);
            }

            public void RemoveByKey(ulong[] keys) {
                foreach (var @ulong in keys) {
                    RemoveByKey(@ulong);
                }
            }

            private static void SetAssetName<T>(ulong guid, string name, Dictionary<ulong, T> map, Dictionary<ulong, ulong> replacements = null) where T : ComboAsset {
                if (replacements != null) guid = GetReplacement(guid, replacements);
                if (!map.TryGetValue(guid, out var asset)) return;
                asset.m_name = name.TrimEnd(' ');
            }

            public void SetEntityName(ulong entity, string name, Dictionary<ulong, ulong> replacements = null) => SetAssetName(entity, name, m_entities, replacements);

            public void SetTextureName(ulong texture, string name, Dictionary<ulong, ulong> replacements = null) => SetAssetName(texture, name, m_textures, replacements);

            public void SetTextureProcessIcon(ulong texture) {
                if (!m_textures.TryGetValue(texture, out var asset)) return;
                asset.m_processIcon = true;
            }

            /// <summary>
            /// Sets save texture options for a texture, these will be used when saving the texture.
            /// </summary>
            /// <remarks>NOTE: If using replacements, these wont work as the guids will be different, in order for these to work, you need to set the options on the replaced guid</remarks>
            public void SetTextureOptions(ulong texture, SaveLogic.Combo.SaveTextureOptions options) {
                if (!m_textures.TryGetValue(texture, out var asset)) return;
                asset.m_split = options.Split;
                asset.m_fileType = options.FileTypeOverride;
                asset.m_processIcon = options.ProcessIcon;
                asset.m_name = options.FileNameOverride;
            }

            public void SetTextureSplit(ulong texture) {
                if (!m_textures.TryGetValue(texture, out var asset)) return;
                asset.m_split = true;
            }

            /// <summary>
            /// Overrides the file type the texture is saved as
            /// </summary>
            /// <param name="texture"></param>
            /// <param name="fileType">tif, png, dds</param>
            public void SetTextureFileType(ulong texture, string fileType) {
                if (!m_textures.TryGetValue(texture, out var asset)) return;
                asset.m_fileType = fileType;
            }

            public void SetEffectName(ulong effect, string name, Dictionary<ulong, ulong> replacements = null) {
                SetAssetName(effect, name, m_effects, replacements);
                SetAssetName(effect, name, m_animationEffects, replacements);
            }

            public void SetModelLookName(ulong look, string name, Dictionary<ulong, ulong> replacements = null) => SetAssetName(look, name, m_modelLooks, replacements);

            public void SetEffectVoiceSet(ulong effect, ulong voiceSet) {
                if (m_animationEffects.ContainsKey(effect)) SetEffectVoiceSet(m_animationEffects[effect], voiceSet);
                if (m_effects.ContainsKey(effect)) SetEffectVoiceSet(m_effects[effect], voiceSet);
            }

            public static void SetEffectVoiceSet(EffectInfoCombo effect, ulong voiceSet) {
                effect.Effect.VoiceSet = voiceSet;
            }
        }

        public class ComboAsset {
            public ulong m_GUID;
            public string m_name;

            protected ComboAsset(ulong guid) {
                m_name = null;
                m_GUID = guid;
                m_name = GetNullableGUIDName(guid);
            }

            public string GetName() {
                if (Program.Flags != null && Program.Flags.NoNames) {
                    return GetFileName(m_GUID);
                }

                return GetValidFilename(m_name) ?? GetFileName(m_GUID);
            }

            public string GetNameIndex() {
                // new model and look
                if (teResourceGUID.Type(m_GUID) == 0x118) return GetName();
                if (teResourceGUID.Type(m_GUID) == 0x119) return GetName();

                return GetName() ?? $"{m_GUID & 0xFFFFFFFFFFFF:X12}";
            }
        }

        public class DisplayTextAsset : ComboAsset {
            public string m_text;

            public DisplayTextAsset(ulong guid, string text) : base(guid) {
                m_text = text;
            }
        }

        public class VoiceSetAsset : ComboAsset {
            public VoiceSetAsset(ulong guid) : base(guid) { }

            public Dictionary<ulong, HashSet<VoiceLineInstanceInfo>> VoiceLineInstances;
            // key = 078 voice stimulus
        }

        public class VoiceLineInstanceInfo {
            public ulong GUIDx06F;
            public ulong GUIDx09B;
            public ulong GUIDx03C;
            public ulong VoiceLineSet;<commit_msg>Fix GetNameIndex adding the type id.<commit_after>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using DataTool.ConvertLogic.WEM;
using DataTool.Helper;
using Newtonsoft.Json;
using TankLib;
using TankLib.Chunks;
using TankLib.STU;
using TankLib.STU.Types;
using static DataTool.Helper.STUHelper;
using static DataTool.Helper.IO;

namespace DataTool.FindLogic {
    public static class Combo {
        private static readonly HashSet<ushort> s_unhandledTypes = new HashSet<ushort>();

        public class ComboInfo {
            // keep everything at top level, stops us from doing the same things again.
            // everything here is unsorted, but we can use GUIDs as references.
            public Dictionary<ulong, EntityAsset> m_entities;
            public Dictionary<ulong, HashSet<ulong>> m_entitiesByIdentifier;
            public Dictionary<ulong, ModelAsset> m_models;
            public Dictionary<ulong, MaterialAsset> m_materials;
            public Dictionary<ulong, MaterialDataAsset> m_materialData;
            public Dictionary<ulong, ModelLookAsset> m_modelLooks;
            public Dictionary<ulong, AnimationAsset> m_animations;
            public Dictionary<ulong, TextureAsset> m_textures;
            public Dictionary<ulong, EffectInfoCombo> m_effects;
            public Dictionary<ulong, EffectInfoCombo> m_animationEffects;
            public Dictionary<ulong, SoundInfoNew> m_sounds;
            public Dictionary<ulong, WWiseBankInfo> m_soundBanks;
            public Dictionary<ulong, SoundFileAsset> m_voiceSoundFiles;
            public Dictionary<ulong, SoundFileAsset> m_soundFiles;
            public Dictionary<ulong, VoiceSetAsset> m_voiceSets;
            public Dictionary<ulong, DisplayTextAsset> m_displayText;
            public Dictionary<ulong, SubtitleAsset> m_subtitles;
            public HashSet<ulong> m_doneScripts;

            public bool m_processExistingEntities = false;
            public bool m_fullLog = false;

            public ComboInfo() {
                m_entities = new Dictionary<ulong, EntityAsset>();
                m_entitiesByIdentifier = new Dictionary<ulong, HashSet<ulong>>();
                m_models = new Dictionary<ulong, ModelAsset>();
                m_materials = new Dictionary<ulong, MaterialAsset>();
                m_materialData = new Dictionary<ulong, MaterialDataAsset>();
                m_modelLooks = new Dictionary<ulong, ModelLookAsset>();
                m_animations = new Dictionary<ulong, AnimationAsset>();
                m_textures = new Dictionary<ulong, TextureAsset>();
                m_effects = new Dictionary<ulong, EffectInfoCombo>();
                m_animationEffects = new Dictionary<ulong, EffectInfoCombo>();
                m_sounds = new Dictionary<ulong, SoundInfoNew>();
                m_soundBanks = new Dictionary<ulong, WWiseBankInfo>();
                m_voiceSoundFiles = new Dictionary<ulong, SoundFileAsset>();
                m_soundFiles = new Dictionary<ulong, SoundFileAsset>();
                m_voiceSets = new Dictionary<ulong, VoiceSetAsset>();
                m_displayText = new Dictionary<ulong, DisplayTextAsset>();
                m_subtitles = new Dictionary<ulong, SubtitleAsset>();
                m_doneScripts = new HashSet<ulong>();
            }

            public void RemoveByKey(ulong key) {
                m_entities.Remove(key);
                m_entitiesByIdentifier.Remove(key);
                m_models.Remove(key);
                m_materials.Remove(key);
                m_materialData.Remove(key);
                m_modelLooks.Remove(key);
                m_animations.Remove(key);
                m_textures.Remove(key);
                m_effects.Remove(key);
                m_animationEffects.Remove(key);
                m_sounds.Remove(key);
                m_soundBanks.Remove(key);
                m_voiceSoundFiles.Remove(key);
                m_soundFiles.Remove(key);
                m_voiceSets.Remove(key);
                m_displayText.Remove(key);
                m_subtitles.Remove(key);
            }

            public void RemoveByKey(ulong[] keys) {
                foreach (var @ulong in keys) {
                    RemoveByKey(@ulong);
                }
            }

            private static void SetAssetName<T>(ulong guid, string name, Dictionary<ulong, T> map, Dictionary<ulong, ulong> replacements = null) where T : ComboAsset {
                if (replacements != null) guid = GetReplacement(guid, replacements);
                if (!map.TryGetValue(guid, out var asset)) return;
                asset.m_name = name.TrimEnd(' ');
            }

            public void SetEntityName(ulong entity, string name, Dictionary<ulong, ulong> replacements = null) => SetAssetName(entity, name, m_entities, replacements);

            public void SetTextureName(ulong texture, string name, Dictionary<ulong, ulong> replacements = null) => SetAssetName(texture, name, m_textures, replacements);

            public void SetTextureProcessIcon(ulong texture) {
                if (!m_textures.TryGetValue(texture, out var asset)) return;
                asset.m_processIcon = true;
            }

            /// <summary>
            /// Sets save texture options for a texture, these will be used when saving the texture.
            /// </summary>
            /// <remarks>NOTE: If using replacements, these wont work as the guids will be different, in order for these to work, you need to set the options on the replaced guid</remarks>
            public void SetTextureOptions(ulong texture, SaveLogic.Combo.SaveTextureOptions options) {
                if (!m_textures.TryGetValue(texture, out var asset)) return;
                asset.m_split = options.Split;
                asset.m_fileType = options.FileTypeOverride;
                asset.m_processIcon = options.ProcessIcon;
                asset.m_name = options.FileNameOverride;
            }

            public void SetTextureSplit(ulong texture) {
                if (!m_textures.TryGetValue(texture, out var asset)) return;
                asset.m_split = true;
            }

            /// <summary>
            /// Overrides the file type the texture is saved as
            /// </summary>
            /// <param name="texture"></param>
            /// <param name="fileType">tif, png, dds</param>
            public void SetTextureFileType(ulong texture, string fileType) {
                if (!m_textures.TryGetValue(texture, out var asset)) return;
                asset.m_fileType = fileType;
            }

            public void SetEffectName(ulong effect, string name, Dictionary<ulong, ulong> replacements = null) {
                SetAssetName(effect, name, m_effects, replacements);
                SetAssetName(effect, name, m_animationEffects, replacements);
            }

            public void SetModelLookName(ulong look, string name, Dictionary<ulong, ulong> replacements = null) => SetAssetName(look, name, m_modelLooks, replacements);

            public void SetEffectVoiceSet(ulong effect, ulong voiceSet) {
                if (m_animationEffects.ContainsKey(effect)) SetEffectVoiceSet(m_animationEffects[effect], voiceSet);
                if (m_effects.ContainsKey(effect)) SetEffectVoiceSet(m_effects[effect], voiceSet);
            }

            public static void SetEffectVoiceSet(EffectInfoCombo effect, ulong voiceSet) {
                effect.Effect.VoiceSet = voiceSet;
            }
        }

        public class ComboAsset {
            public ulong m_GUID;
            public string m_name;

            protected ComboAsset(ulong guid) {
                m_name = null;
                m_GUID = guid;
                m_name = GetNullableGUIDName(guid);
            }

            public string GetName() {
                if (Program.Flags is { NoNames: true }) {
                    return GetFileName(m_GUID);
                }

                return GetValidFilename(m_name) ?? GetFileName(m_GUID);
            }

            public string GetNameIndex() {
                string fallback;
                switch (teResourceGUID.Type(m_GUID)) {
                    // new model and look
                    case 0x118:
                    case 0x119:
                        fallback = GetFileName(m_GUID);
                        break;
                    default:
                        fallback = $"{m_GUID & 0xFFFFFFFFFFFF:X12}";
                        break;
                }

                if (Program.Flags is { NoNames: true }) {
                    return fallback;
                }

                return GetValidFilename(m_name) ?? fallback;
            }
        }

        public class DisplayTextAsset : ComboAsset {
            public string m_text;

            public DisplayTextAsset(ulong guid, string text) : base(guid) {
                m_text = text;
            }
        }

        public class VoiceSetAsset : ComboAsset {
            public VoiceSetAsset(ulong guid) : base(guid) { }

            public Dictionary<ulong, HashSet<VoiceLineInstanceInfo>> VoiceLineInstances;
            // key = 078 voice stimulus
        }

        public class VoiceLineInstanceInfo {
            public ulong GUIDx06F;
            public ulong GUIDx09B;
            public ulong GUIDx03C;
            public ulong VoiceLineSet;
{'fraction_non_alphanumeric': 0.08251218191662155, 'fraction_numerical': 0.002165674066053059, 'mean_word_length': 2.0305168170631664, 'pattern_counts': {'":': 0, '<': 121, '<?xml version=': 0, '>': 127, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '4908787', 'n_tokens_mistral': 4960, 'n_tokens_neox': 4657, 'n_words': 1187}