using EDPlayerJournal.Entries;

namespace EDPlayerJournal; 
public class JournalStream {
    private FileSystemWatcher? watcher = null;

    private Dictionary<string, StreamReader> streams = new Dictionary<string, StreamReader>();

    public delegate void NewJournalEntryDelegate(Entry entry);

    public event NewJournalEntryDelegate? NewJournalEntry;

    public PlayerJournal? Journal;

    public JournalStream() {
    }

    public JournalStream(PlayerJournal journal) {
        Journal = journal;
        Open();
    }

    private void AddFileToStreams(string path, bool seekend = false) {
        if (!streams.ContainsKey(path) && JournalFile.VerifyFile(path)) {
            var filestream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            streams[path] = new StreamReader(filestream);

            if (seekend) {
                streams[path].BaseStream.Seek(0, SeekOrigin.End);
            }
        }
    }

    public void Open() {
        if (watcher != null) {
            return;
        }

        if (Journal == null || Journal.Location == null) {
            return;
        }

        if (Journal.Files.Count > 0) {
            JournalFile lastfile = Journal.GetLastFile();
            /* add last file to stream */
            AddFileToStreams(lastfile.FullPath, true);
        }

        watcher = new FileSystemWatcher(Journal.Location);

        watcher.NotifyFilter = NotifyFilters.FileName |
            NotifyFilters.LastWrite |
            NotifyFilters.Size;

        watcher.Changed += Watcher_Changed;
        watcher.Created += Watcher_Created;

        watcher.Filter = "*.log";
        watcher.EnableRaisingEvents = true;
    }

    public void Close() {
        if (watcher != null) {
            watcher.EnableRaisingEvents = false;
        }
        watcher = null;
        streams.Clear();
    }

    private void Watcher_Created(object sender, FileSystemEventArgs e) {
        AddFileToStreams(e.FullPath);
    }

    private void Watcher_Changed(object sender, FileSystemEventArgs e) {
        AddFileToStreams(e.FullPath);

        var stream = streams[e.FullPath];
        if (stream == null) {
            return;
        }

        string? line;

        while ((line = stream.ReadLine()) != null) {
            try {
                Entry? entry = Entry.Parse(line);
                if (entry != null) {
                    NewJournalEntry?.Invoke(entry);
                }
            } catch (Exception) {
            }
        }
    }
}
