using Cryville.Crtr.Browsing.Actions; using Cryville.Crtr.Extension; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace Cryville.Crtr.Browsing.Legacy { internal abstract class LegacyResourceManager : IPathedResourceManager where T : IResourceMeta { protected readonly LegacyResourceStore _store; DirectoryInfo _cd; readonly FileSystemWatcher _watcher = new(); DirectoryInfo[] _items = new DirectoryInfo[0]; DirectoryInfo[] _filteredItems = new DirectoryInfo[0]; string _filter = string.Empty; readonly List _dirParts = new(); readonly IList m_dirParts; public IList CurrentDirectory { get { return m_dirParts; } } public int Count { get { return _filteredItems.Length; } } public event Action ItemChanged; public event Action DirectoryChanged; public LegacyResourceManager(LegacyResourceStore store) { _store = store; _store.ResourceImported += ReloadFiles; m_dirParts = _dirParts.AsReadOnly(); _watcher.Changed += OnFileChanged; _watcher.Created += OnFileChanged; _watcher.Deleted += OnFileChanged; _watcher.Renamed += OnFileChanged; _watcher.Error += OnFileWatcherError; OnDirectoryChange(); } void OnFileWatcherError(object sender, ErrorEventArgs e) { Game.MainLogger.Log(4, "Data", "An error occurred while watching file changes: {0}", e.GetException()); } void OnFileChanged(object sender, FileSystemEventArgs e) { ReloadFiles(); } public void Activate() { _watcher.EnableRaisingEvents = !string.IsNullOrEmpty(_watcher.Path); } public void Deactivate() { _watcher.EnableRaisingEvents = false; } protected abstract string GetSubRootPath(string rootPath); protected void ReloadFiles() { _items = _cd.GetDirectories(); ApplyFilter(); } void OnDirectoryChange() { string path = Path.Combine(GetSubRootPath(_store.RootPath), string.Join(Path.DirectorySeparatorChar, _dirParts)); _cd = new DirectoryInfo(path); _watcher.Path = path; _watcher.EnableRaisingEvents = true; ReloadFiles(); DirectoryChanged?.Invoke(); } public void ChangeDirectory(IEnumerable dir) { _dirParts.Clear(); foreach (string dirPart in dir) _dirParts.Add(dirPart); OnDirectoryChange(); } public bool IsDirectory(int index) { return _filteredItems[index].GetFiles(Extension).Length == 0; } public void OpenDirectory(int index) { _dirParts.Add(_filteredItems[index].Name); OnDirectoryChange(); } public void ReturnToDirectory(int index) { _dirParts.RemoveRange(index + 1, _dirParts.Count - index - 1); OnDirectoryChange(); } public void ApplyFilter(string filter) { _filter = filter; ApplyFilter(); } void ApplyFilter() { IEnumerable items = _items; foreach (var keyword in _filter.Split(' ', StringSplitOptions.RemoveEmptyEntries)) { items = items.Where(i => i.Name.Contains(keyword, StringComparison.CurrentCultureIgnoreCase)); } _filteredItems = items.ToArray(); ItemChanged?.Invoke(); } protected abstract T GetMeta(DirectoryInfo dir); public T this[int index] { get { var item = _filteredItems[index]; return GetMeta(item); } } IResourceMeta IResourceManager.this[int index] { get { return this[index]; } } protected abstract string Extension { get; } public Uri GetItemUri(int index) { var item = _filteredItems[index]; var meta = new ChartMeta(); var metaFile = new FileInfo(Path.Combine(item.FullName, Extension)); using (var reader = new StreamReader(metaFile.FullName)) { meta = JsonConvert.DeserializeObject(reader.ReadToEnd()); } return new Uri(PlatformConfig.FileProtocolPrefix + Path.Combine(_filteredItems[index].FullName, string.Format("{0}.json", meta.data))); } public bool IsReadOnly { get { return false; } } public void RemoveAt(int index) { _filteredItems[index].Delete(true); } public abstract IResourceAction GetImportAction(); } }