using System;
using AcDream.Core.Chat;
using AcDream.UI.Abstractions.Panels.Chat;
namespace AcDream.App.UI;
///
/// Copies the chat transcript into retail's @log file.
///
///
///
/// Retail's log write sits INSIDE ClientSystem::AddTextToScroll
/// (fprintf(s_pLogFile, "%ls%ls\n", …) @0x00563E5B) — downstream of
/// composition and upstream of glyph layout. So the log records the finished
/// display line, timestamp included, and does not re-derive one.
/// is acdream's equivalent single fan-in.
///
///
/// Attaching happens on OPEN rather than at startup, which is what retail's
/// own help promises: "All the information that appears in your chat window
/// AFTER you type this command will be copied into a text file."
///
///
public sealed class ChatTranscriptLogWriter
{
private readonly ChatSessionLog _log;
private ChatLog? _source;
public ChatTranscriptLogWriter(ChatSessionLog log)
=> _log = log ?? throw new ArgumentNullException(nameof(log));
///
/// Starts copying , detaching from whatever was
/// attached before. Re-attaching to the same transcript does not double
/// up.
///
public void Attach(ChatLog source)
{
ArgumentNullException.ThrowIfNull(source);
Detach();
_source = source;
source.EntryAppended += Write;
}
///
/// Stops copying. Detaches from the instance actually attached to, not
/// from whatever is current — a transcript replaced mid-log must not leave
/// a handler behind on the old one.
///
public void Detach()
{
if (_source is null)
return;
_source.EntryAppended -= Write;
_source = null;
}
private void Write(ChatEntry entry)
{
ChatLog? source = _source;
if (source is null)
return;
// The SAME gate the window uses, so a log never disagrees with the
// transcript it is a copy of.
bool stamped = source.DisplayTimestampsSource?.Invoke() == true;
_log.Write(
stamped ? ChatLog.FormatTimestampPrefix(entry.Received) : null,
ChatVM.FormatEntry(entry));
}
}