using System;
using System.Collections.Generic;
using System.Text;
using FMOD;

namespace ChtiCanon
{
    public static class CanonAudio
    {
        public class Sound
        {
            public delegate void EndMusicEventHandler(Sound m);
            private FMOD.Sound sound = null;
            private Channel musicChannel = null;
            private CHANNEL_CALLBACK channelCallback;
            public event EndMusicEventHandler EndMusic;

            public Sound(string path, bool loop)
            {
                RESULT result = system.createSound(path, MODE.SOFTWARE | MODE.CREATECOMPRESSEDSAMPLE | (loop ? MODE.LOOP_NORMAL : MODE.LOOP_OFF), ref sound);
                ErrCheck(result);
                channelCallback = new CHANNEL_CALLBACK(OnEnd);
            }

            ~Sound()
            {
                if (sound != null)
                    sound.release();
            }

            public void Play()
            {
                const bool paused = false;
                // Déjà en train de jouer?
                if (musicChannel != null)
                    Stop();
                RESULT result = system.playSound(CHANNELINDEX.FREE, sound, paused, ref musicChannel);
                ErrCheck(result);
                musicChannel.setCallback(channelCallback);
            }

            public void Stop()
            {
                if (musicChannel != null)
                {
                    RESULT result = musicChannel.stop();
                    musicChannel = null;
                    ErrCheck(result);
                }
            }

            public bool Paused
            {
                get
                {
                    bool paused = false;
                    if (musicChannel == null)
                        return false;
                    ErrCheck(musicChannel.getPaused(ref paused));
                    return paused;
                }
                set
                {
                    if (musicChannel != null)
                        ErrCheck(musicChannel.setPaused(value));
                }
            }

            public RESULT OnEnd(IntPtr channelraw, FMOD.CHANNEL_CALLBACKTYPE type, IntPtr arg1, IntPtr arg2)
            {
                if (type == CHANNEL_CALLBACKTYPE.END)
                {
                    // Signale l'événement
                    if (EndMusic != null)
                        EndMusic(this);
                    musicChannel = null;
                }
                return RESULT.OK;
            }
        }

        private static FMOD.System system = null;

        private static void ErrCheck(RESULT result)
        {
            if (result != RESULT.OK)
            {
                throw new ApplicationException("FMOD error! " + result + " - " + Error.String(result));
            }
        }

        public static bool Initialize()
        {
            RESULT result;

            result = Factory.System_Create(ref system);
            ErrCheck(result);

            uint version = 0;

            result = system.getVersion(ref version);
            ErrCheck(result);

            if (version < VERSION.number)
                throw new ApplicationException("Error! You are using an old version of FMOD " + version.ToString("X") + ". This program requires " + VERSION.number.ToString("X") + ".");

            result = system.init(32, INITFLAG.NORMAL, (IntPtr)null);
            ErrCheck(result);
            return true;
        }

        public static void Deinitialize()
        {
            system.release();
        }

        public static void Update()
        {
            system.update();
        }
    }
}
