using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
namespace Urovo
{
    #region PowerNotify Event
    /// 
    /// PowerNotifyEventArgs
    /// 
    public class PowerNotifyEventArgs : EventArgs
    {
        private uint acLineStatus;
        private uint batteryLifePercent;
        public uint ACLineStatus
        {
            get { return acLineStatus; }
        }
        public uint BatteryLifePercent
        {
            get { return batteryLifePercent; }
        }
        public PowerNotifyEventArgs(uint acLineStatus, uint batteryLifePercent)
        {
            this.acLineStatus = acLineStatus;
            this.batteryLifePercent = batteryLifePercent;
        }
    }
    /// 
    ///  PowerNotifyEvent Delegate
    /// 
    /// 
    /// 
    public delegate void PowerNotifyEventHandler(object sender, PowerNotifyEventArgs e);
    #endregion
    public class PowerManager
    {
  
        #region Event
        public event PowerNotifyEventHandler PowerNotify = null;
        protected virtual void OnPowerNotify(PowerNotifyEventArgs e)
        {
            if (PowerNotify != null)
            {
                PowerNotify(this, e);
            }
        }
        #endregion
        #region Variable
        IntPtr hMsgQ;
        IntPtr hNotify;
        IntPtr[] hEvent = new IntPtr[2];
        #endregion
        #region Method
        /// 
        /// Start  PowerManagement Thread
        /// 
        /// 
        public bool Start()
        {
            hEvent[0] = Win32.CreateEvent(IntPtr.Zero, false, false, null);
            Win32.MSGQUEUEOPTIONS options = new Win32.MSGQUEUEOPTIONS();
            options.dwSize = 20;
            options.dwFlags = 2;
            options.dwMaxMessages = 1;
            options.cbMaxMessage = 64;
            options.bReadAccess = true;
            hMsgQ = Win32.CreateMsgQueue(null, options);
            if (hMsgQ == IntPtr.Zero)
            {
                return false;
            }
            hNotify = Win32.RequestPowerNotifications(hMsgQ, Win32.PBT_POWERINFOCHANGE);
            if (hNotify == IntPtr.Zero)
            {
                return false;
            }
            hEvent[1] = hMsgQ;
            Thread t = new Thread(new ThreadStart(this.PowerThreadPorc));
            t.Start();
            return true;
        }
        /// 
        /// Stop PowerManagement Thread
        /// 
        public void Stop()
        {
            PowerNotify = null;
            Win32.EventModify(hEvent[0], Win32.EVENT_SET);
            Win32.StopPowerNotifications(hNotify);
            Win32.CloseMsgQueue(hMsgQ);
            Win32.CloseHandle(hEvent[0]);
        }
        /// 
        /// PowerThreadPorc
        /// 
        private void PowerThreadPorc()
        {
            while (true)
            {
                uint evt = Win32.WaitForMultipleObjects(2, hEvent, false, Win32.INFINITE);
                switch (evt)
                {
                    case 0:     //return thread
                        return;
                    case 1:
                        uint bytesRead;
                        uint flags;
                        Win32.POWER_BROADCAST pB = new Win32.POWER_BROADCAST();
                        if (Win32.ReadMsgQueue(hMsgQ, out pB, (uint)Marshal.SizeOf(typeof(Win32.POWER_BROADCAST)), out bytesRead, Win32.INFINITE, out flags))
                        {
                            if (pB.Message == Win32.PBT_POWERINFOCHANGE && pB.PI.bACLineStatus != 0x01 && pB.PI.bBatteryLifePercent <= 5)
                            {
                                Win32.SetSystemPowerState(null, Win32.POWER_STATE_SUSPEND, Win32.POWER_FORCE);
                                break;
                            }
                            OnPowerNotify(new PowerNotifyEventArgs(pB.PI.bACLineStatus, pB.PI.bBatteryLifePercent));
                        }
                        break;
                }
            }
        }
        #endregion
    }
}