<commit_before>﻿using AudioWorks.Common;
using JetBrains.Annotations;
using System.IO;
using System.Runtime.InteropServices;

namespace AudioWorks.Extensions.Flac
{
    [AudioMetadataEncoderExport(".flac")]
    sealed class FlacAudioMetadataEncoder : IAudioMetadataEncoder
    {
        public SettingInfoDictionary GetSettingInfo()
        {
            return new SettingInfoDictionary
            {
                ["Padding"] = new IntSettingInfo(0, 16_777_216)
            };
        }

        public void WriteMetadata(FileStream stream, AudioMetadata metadata, SettingDictionary settings)
        {
            var padding = GetPadding(settings);
            NativeVorbisCommentBlock vorbisCommentBlock = null;

            try
            {
                using (var chain = new NativeMetadataChain(stream))
                {
                    chain.Read();

                    vorbisCommentBlock = new MetadataToVorbisCommentAdapter(metadata);

                    // Iterate over the existing blocks, replacing and deleting as needed:
                    using (var iterator = chain.GetIterator())
                        UpdateChain(iterator, vorbisCommentBlock, padding);

                    // If FLAC requests a temporary file, use a MemoryStream instead. Then overwrite the original:
                    if (chain.CheckIfTempFileNeeded(!padding.HasValue))
                        using (var tempStream = new MemoryStream())
                        {
                            chain.WriteWithTempFile(!padding.HasValue, tempStream);

                            // Clear the original stream, and copy the temporary one over it:
                            stream.SetLength(tempStream.Length);
                            stream.Position = 0;
                            tempStream.WriteTo(stream);
                        }
                    else
                        chain.Write(!padding.HasValue);
                }
            }
            finally
            {
                vorbisCommentBlock?.Dispose();
            }

        }

        [Pure]
        int? GetPadding([NotNull] SettingDictionary settings)
        {
            if (!settings.TryGetValue("Padding", out var stringValue))
                return null;
            return (int) stringValue;
        }

        static void UpdateChain(
            [NotNull] NativeMetadataIterator iterator,
            [NotNull] NativeVorbisCommentBlock newComments,
            int? padding)
        {
            var metadataInserted = false;

            do
            {
                switch ((MetadataType) Marshal.ReadInt32(iterator.GetBlock()))
                {
                    // Replace the existing Vorbis comment<commit_msg>Refactoring.<commit_after>﻿using AudioWorks.Common;
using JetBrains.Annotations;
using System.IO;
using System.Runtime.InteropServices;

namespace AudioWorks.Extensions.Flac
{
    [AudioMetadataEncoderExport(".flac")]
    sealed class FlacAudioMetadataEncoder : IAudioMetadataEncoder
    {
        public SettingInfoDictionary GetSettingInfo()
        {
            return new SettingInfoDictionary
            {
                ["Padding"] = new IntSettingInfo(0, 16_777_216)
            };
        }

        public void WriteMetadata(FileStream stream, AudioMetadata metadata, SettingDictionary settings)
        {
            var padding = GetPadding(settings);

            using (var chain = new NativeMetadataChain(stream))
            using (var comments = new MetadataToVorbisCommentAdapter(metadata))
            {
                chain.Read();

                // Iterate over the existing blocks, replacing and deleting as needed:
                using (var iterator = chain.GetIterator())
                    UpdateChain(iterator, comments, padding);

                // If FLAC requests a temporary file, use a MemoryStream instead. Then overwrite the original:
                if (chain.CheckIfTempFileNeeded(!padding.HasValue))
                    using (var tempStream = new MemoryStream())
                    {
                        chain.WriteWithTempFile(!padding.HasValue, tempStream);

                        // Clear the original stream, and copy the temporary one over it:
                        stream.SetLength(tempStream.Length);
                        stream.Position = 0;
                        tempStream.WriteTo(stream);
                    }
                else
                    chain.Write(!padding.HasValue);
            }
        }

        [Pure]
        int? GetPadding([NotNull] SettingDictionary settings)
        {
            if (!settings.TryGetValue("Padding", out var stringValue))
                return null;
            return (int) stringValue;
        }

        static void UpdateChain(
            [NotNull] NativeMetadataIterator iterator,
            [NotNull] NativeVorbisCommentBlock newComments,
            int? padding)
        {
            var metadataInserted = false;

            do
            {
                switch ((MetadataType) Marshal.ReadInt32(iterator.GetBlock()))
                {
                    // Replace the existing Vorbis comment
{'fraction_non_alphanumeric': 0.0708600271791885, 'fraction_numerical': 0.004659289458357601, 'mean_word_length': 1.5479723046488625, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, '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': '5713611', 'n_tokens_mistral': 1188, 'n_tokens_neox': 1108, 'n_words': 287}