using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Xml;
using System.Threading;
using System.Windows.Forms;
using System.IO;


namespace ChuPiao.Common.Utils
{
    public class BeepUtil : IDisposable
    {
        public const int MB_OK = 0;
        public const int MB_ICONSTOP = 16;
        public const int MB_ICONEXCLAMATION = 48;
        public const int MB_ICONINFORMATION = 64;

        public const uint beepl = 0x00000000; //发出不同类型的声音的参数如下：   //Ok = 0x00000000, //Error = 0x00000010, //Question = 0x00000020, //Warning = 0x00000030, //Information = 0x00000040 

        private bool iswin7 = false;
        public static bool notUseBeep = false;
        public static string fileToPlay = "";

        [DllImport("user32.dll")]
        public static extern bool MessageBeep(uint uType);

        [DllImport("kernel32.dll", EntryPoint = "Beep")]
        public static extern int Beep(int dwFreq, int dwDuration);

        [DllImport("winmm.dll")] 
        public  static  extern  bool  PlaySound(string  pszSound,int hmod,int fdwSound);  
        public const int SND_FILENAME = 0x00020000; 
        public const int SND_ASYNC = 0x0001;

        /// <summary>   
        /// API函数   
        /// </summary>   
        [DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Auto)]
        private static extern int mciSendString(
         string lpstrCommand,
         string lpstrReturnString,
         int uReturnLength,
         int hwndCallback
        );  
        

        private int _currentid;
        public int Currentid
        {
            set { _currentid = value; }
            get { return _currentid; }
        }

        private Dictionary<int,int[,]> _soundList;
        public Dictionary<int, int[,]> SoundList
        {
            get { return _soundList; }
            set { _soundList = value; }
        }

        private int _previewid;
        public int Previewid
        {
            set { _previewid = value; }
            get { return _previewid; }
        }

        //标识是否播放
        private bool _isStop;
        private bool _isRunning;
        private EventWaitHandle _waitHandle;
        private Thread _playThread;
        private int _playType;
        private int[,] _cells;

        private static BeepUtil _beepUtil;
        /// <summary>
        /// 单例获取BeepUtil
        /// </summary>
        public static BeepUtil Instance()
        {
            if (_beepUtil == null)
            {
                _beepUtil = new BeepUtil();
            }
            return _beepUtil;
        }

        private BeepUtil()
        {
            LoadConfig();
            _waitHandle = new EventWaitHandle(false,EventResetMode.AutoReset);
            _isStop = true;
            _isRunning = true;
            _playType = -1;
            _playThread = new Thread(new ThreadStart(PlayMusicTask));
        }

        /// <summary>
        /// 播放当前音乐
        /// </summary>
        public void StartCurrent()
        {
            StartPlay(0);
        }

        public void StopCurrent()
        {
            StopPlay();
        }

        /// <summary>
        /// 播放试听音乐
        /// </summary>
        public void StartPreview()
        {
            StartPlay(1);
        }

        public void StopPreview()
        {
            StopPlay();
        }

        private void StartPlay(int playType)
        {
            lock (this)
            {
                if (playType == _playType && !_isStop)
                {
                    return;
                }
                _playType = playType;
                _isStop = true;
                PreparePlayMusic();
                _isStop = false;
                if (_playThread.ThreadState == ThreadState.Unstarted)
                {
                    _playThread.Start();
                }
                else if (_playThread.ThreadState == ThreadState.WaitSleepJoin)
                {
                    _waitHandle.Set();
                }
            }
        }

        private void StopPlay()
        {
            lock (this)
            {
                _isStop = true;
            }
        }

        private void PreparePlayMusic()
        {
            lock (this.GetType())
            {
                if (_playType == 0)
                {
                    _cells = _soundList[_currentid];
                }
                else
                {
                    _cells = _soundList[_previewid];
                }
            }
        }
        /// <summary>
        /// 播放音乐
        /// </summary>
        private void PlayMusicTask()
        {
            while (_isRunning)
            {
                lock (this.GetType())
                {
                    while (!_isStop)
                    {
                        //if (iswin7)
                        //{
                        //    MessageBeep(beepl);
                        //    Thread.Sleep(1000);
                        //}
                        if (notUseBeep)
                        {
                            //PlaySound(fileToPlay, 0, 9);      //把1替换成9，可连续播放

                            //mciSendString("close all", "", 0, 0);
                            //mciSendString("open \"" + fileToPlay + "\" alias media", "", 0, 0);
                            //mciSendString("play media", "", 0, 0);  

                            //MessageBeep(beepl);

                            //Thread.Sleep(1000);
                        }
                        else
                        {
                            for (int i = 0; i < _cells.GetLength(0); i++)
                            {
                                if (!_isStop)
                                {
                                    Beep(_cells[i, 0], _cells[i, 1]);
                                }
                            }
                        }
                    }
                }
                _waitHandle.WaitOne();
            }
        }

        /// <summary>
        /// 从配置文件中读取声音列表和当前声音id
        /// </summary>
        public void LoadConfig() 
        {
            //if (ApplicationUtil.IsWindows7)
            //{
            //    iswin7 = true;
            //}

            XmlDocument doc = new XmlDocument();
            //当软件自动启动时，当前目录是C:\Windows\system32,所以不能用相对路径，要用绝对的
            doc.Load(Application.StartupPath+"/configs/sound.xml");

            XmlNode sounds = doc.SelectSingleNode("sounds");
            _currentid = Convert.ToInt32(sounds.Attributes["current"].Value);

            XmlNodeList soundNodes = sounds.SelectNodes("sound");
            _soundList = new Dictionary<int, int[,]>();
            foreach (XmlNode node in soundNodes)
            {
                string[] musicTextArray = node.InnerText.Split(';');
                int[,] musicText = new int[musicTextArray.Length, 2];
                for (int i = 0; i < musicTextArray.Length; i++ )
                {
                    string[] note = musicTextArray[i].Split(',');
                    musicText[i,0] = Convert.ToInt32(note[0]);
                    musicText[i, 1] = Convert.ToInt32(note[1]);
                }
                _soundList.Add(Convert.ToInt32(node.Attributes["id"].Value), musicText);
            }

            //是不是beep发声，默认是
            bool result = false;
            string strtmp = LocalConfigUtil.GetConfig("notUseBeep");
            bool.TryParse(strtmp, out result);
            notUseBeep = result;


            strtmp = LocalConfigUtil.GetConfig("fileToPlay");
            if (string.IsNullOrEmpty(strtmp))
            {
                strtmp = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "default.mp3");
            }
            fileToPlay=strtmp;
        }

        /// <summary>
        /// 修改配置文件
        /// </summary>
        /// <param name="id"></param>
        public void UpdateConfig()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("configs/sound.xml");
            XmlNode sounds = doc.SelectSingleNode("sounds");
            sounds.Attributes["current"].Value = _currentid.ToString();
            doc.Save("configs/sound.xml");
        }

        #region IDisposable 成员

        public void Dispose()
        {
            _isStop = true;
            _isRunning = false;
            _waitHandle.Set();
        }

        #endregion
    }
}
