using System.Text;
using GsaEditor.Core.Models;

namespace GsaEditor.Core.IO;

/// <summary>
/// Writes a .idx NML index file from a <see cref="GsaArchive"/>.
/// The NML format is the engine's own tag syntax (NOT standard XML):
/// <code>
/// &lt;Version=1.0&gt;
/// &lt;Index=
///     &lt;Entry=
///         &lt;ID="path/in/archive"&gt;
///         &lt;CompLen=123&gt;
///         &lt;Len=456&gt;
///         &lt;Offset=789&gt;
///         &lt;Method="Zlib"&gt;
///     &gt;
/// &gt;
/// </code>
/// Tab indentation, LF line endings, no BOM. Method is "Zlib" or "Raw".
/// The engine parses this file to locate entries, so the format must match exactly.
/// </summary>
public static class GsaIndexWriter
{
    /// <summary>
    /// The engine's bootstrap script is loaded by sequential archive scan and is
    /// deliberately absent from the shipped index files, so it is skipped here too.
    /// </summary>
    private const string BootstrapAlias = "bootstrap.txt";

    /// <summary>
    /// Writes the index file for the given archive to the specified path.
    /// Entry offsets must be up to date (i.e. call after <see cref="GsaWriter.Write(GsaArchive, string)"/>).
    /// </summary>
    /// <param name="archive">The archive whose entries will be indexed.</param>
    /// <param name="filePath">The output .idx file path.</param>
    public static void Write(GsaArchive archive, string filePath)
    {
        var sb = new StringBuilder();
        sb.Append("<Version=1.0>\n");
        sb.Append("<Index=\n");

        foreach (var e in archive.Entries)
        {
            if (string.Equals(e.Alias, BootstrapAlias, StringComparison.OrdinalIgnoreCase))
                continue;

            sb.Append("\t<Entry=\n");
            sb.Append("\t\t<ID=\"").Append(e.Alias).Append("\">\n");
            sb.Append("\t\t<CompLen=").Append(e.CompressedLength).Append(">\n");
            sb.Append("\t\t<Len=").Append(e.OriginalLength).Append(">\n");
            sb.Append("\t\t<Offset=").Append(e.DataOffset).Append(">\n");
            sb.Append("\t\t<Method=\"").Append(e.IsCompressed ? "Zlib" : "Raw").Append("\">\n");
            sb.Append("\t>\n");
        }

        sb.Append(">\n");

        File.WriteAllText(filePath, sb.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
    }
}
