using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using SFML.Audio;
using YourBeatingHeart.Main.Helper;

namespace YourBeatingHeart.Main.Sound
{
    public class SoundManager
    {
        [Serializable]
        protected class SoundConfig : ISerializable
        {
            private static string FILENAME = "soundConfig";

            private bool _soundActive;

            private SoundConfig(bool soundActive)
            {
                _soundActive = soundActive;
            }

            public SoundConfig(SerializationInfo info, StreamingContext context)
            {
                _soundActive = info.GetBoolean("SoundActive");
            }

            public static SoundConfig Load()
            {
                SoundConfig soundConfig = null;
                try
                {
                    soundConfig = SerializationHelper.DeserializeObject(FILENAME) as SoundConfig;
                }
                catch
                {
                }
                if (soundConfig == null)
                {
                    soundConfig = new SoundConfig(true);
                }
                return soundConfig;
            }

            public bool Save()
            {
                return SerializationHelper.SerializeObject(FILENAME, this);
            }

            public bool SoundActive
            {
                get { return _soundActive; }
                set
                {
                    if (_soundActive == value)
                        return;

                    _soundActive = value;
                    Save();
                }
            }

            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {
                info.AddValue("SoundActive", _soundActive);
            }
        }

        private static SoundManager _instance;
        public static SoundManager Instance { get { return _instance ?? (_instance = new SoundManager()); } }

        private Dictionary<SoundEvent, string> soundFiles;
        private Dictionary<SoundEvent, SFML.Audio.Sound> sounds;

        private SoundConfig soundConfig;

        private SoundManager()
        {
            soundConfig = SoundConfig.Load();

            soundFiles = new Dictionary<SoundEvent, string>();

            string extension = ".wav";


            soundFiles[SoundEvent.Execute] = "Execute" + extension;
            soundFiles[SoundEvent.Execute2] = "Execution2" + extension;
            soundFiles[SoundEvent.Execute3] = "Execution3" + extension;
            soundFiles[SoundEvent.HeartBeat] = "HeartBeat" + extension;
            soundFiles[SoundEvent.Jump] = "Jump" + extension;
            soundFiles[SoundEvent.JumpLand] = "JumpLand" + extension;
            soundFiles[SoundEvent.Spawn] = "Spawn" + extension;
            soundFiles[SoundEvent.TempleBlood] = "TempleBlood" + extension;
            soundFiles[SoundEvent.Throw] = "Throw" + extension;
            soundFiles[SoundEvent.TowerBurp] = "TowerBurp" + extension;
            soundFiles[SoundEvent.TowerCrush] = "TowerCrush" + extension;
            soundFiles[SoundEvent.Scream] = "Scream1" + extension;
            soundFiles[SoundEvent.AnnouncerStart1] = "Voc_TrialsBegin" + extension;
            soundFiles[SoundEvent.AnnouncerStart2] = "Voc_TrialsBegin2" + extension;
            soundFiles[SoundEvent.AnnouncerBlood1] = "Voc_Quench" + extension;
            soundFiles[SoundEvent.AnnouncerBlood2] = "Voc_Blood" + extension;
            soundFiles[SoundEvent.Winner] = "Voc_Winner" + extension;
            /*
            if (Constants.DEBUG_SOUND_DROPBOX) {
                extension = ".wav";
            }
             */

            //soundFiles[SoundEvent.Jump] = "jump" + extension;
        }

        public bool SoundActive
        {
            get { return soundConfig.SoundActive; }
            set { soundConfig.SoundActive = value; }
        }

        public void PreloadSounds()
        {
            sounds = new Dictionary<SoundEvent, SFML.Audio.Sound>();
            foreach (SoundEvent soundEvent in soundFiles.Keys)
            {
                LoadSound(soundEvent);
            }
        }

        private bool LoadSound(SoundEvent soundEvent)
        {
            if (!soundFiles.ContainsKey(soundEvent))
                return false;

            SoundBuffer soundBuffer;
            if (Constants.DEBUG_SOUND_DROPBOX)
            {
                soundBuffer = new SoundBuffer("D:\\Dropbox\\Dropbox\\Shared\\Gamedev\\KinectTetris\\sounds\\" + soundFiles[soundEvent]);
            }
            else
            {
                string path = Path.Combine(Constants.FOLDER_SOUNDS, soundFiles[soundEvent]);
                soundBuffer = new SoundBuffer(path);
            }

            SFML.Audio.Sound sound = new SFML.Audio.Sound(soundBuffer);
            sounds[soundEvent] = sound;

            return true;
        }

        public void PlaySound(SoundEvent soundEvent)
        {
            if (!soundConfig.SoundActive)
                return;

            // Reload every time for hot swapping while execution?
            if (Constants.DEBUG_RELOAD_SOUND_EVERY_TIME)
            {
                if (!LoadSound(soundEvent))
                {
                    return;
                }
            }

            if (!sounds.ContainsKey(soundEvent))
            {
                if (!LoadSound(soundEvent))
                {
                    return;
                }
            }

            sounds[soundEvent].Play();
        }
    }
}
