﻿using System;
using System.IO;

namespace Oni.Sound
{
    internal class AifExporter : SoundExporter
    {
        #region Private data
        private bool do_pc_demo_test;

        private const int fcc_FORM = 0x464f524d;
        private const int fcc_AIFC = 0x41494643;
        private const int fcc_COMM = 0x434f4d4d;
        private const int fcc_ima4 = 0x696d6134;
        private const int fcc_SSND = 0x53534e44;

        private static readonly byte[] sampleRate = new byte[10]
        {
            0x40, 0x0d, 0xac, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        };

        #endregion

        public AifExporter(InstanceFileManager fileManager, string outputDirPath, bool noDemo = false)
            : base(fileManager, outputDirPath)
        {
            do_pc_demo_test = !noDemo;
        }

        protected override void ExportInstance(InstanceDescriptor descriptor)
        {
            var sound = SoundData.Read(descriptor, do_pc_demo_test);
            if (!(sound.IsIMA4))
                throw new NotSupportedException("Transcoding from MS ADPCM (PC) to IMA4 ADPCM (Mac) not supported!");

            using (var stream = File.Create(Path.Combine(OutputDirPath, descriptor.FullName + ".aif")))
            using (var writer = new BinaryWriter(stream))
            {
                writer.Write(Utils.ByteSwap(fcc_FORM));
                writer.Write(Utils.ByteSwap(50 + sound.Data.Length));
                writer.Write(Utils.ByteSwap(fcc_AIFC));

                //
                // write COMM chunk
                //

                writer.Write(Utils.ByteSwap(fcc_COMM));
                writer.Write(Utils.ByteSwap(22));                   // chunk size
                writer.Write(Utils.ByteSwap((short)sound.ChannelCount));
                writer.Write(Utils.ByteSwap(sound.Data.Length / (sound.ChannelCount * 34))); // numSampleFrames
                writer.Write(Utils.ByteSwap((short)16));            // sampleSize
                writer.Write(sampleRate);                           // sampleRate
                writer.Write(Utils.ByteSwap(fcc_ima4));

                //
                // write SSND chunk
                //

                writer.Write(Utils.ByteSwap(fcc_SSND));
                writer.Write(Utils.ByteSwap(8 + sound.Data.Length)); // chunk size
                writer.Write(0);
                writer.Write(0);
                writer.Write(sound.Data);
            }
        }

    }
}
