/***************************************************************************
 * Copyright (c) 2009 Digi International Inc., All Rights Reserved
 * 
 * This software contains proprietary and confidential information of Digi
 * International Inc.  By accepting transfer of this copy, Recipient agrees
 * to retain this software in confidence, to prevent disclosure to others,
 * and to make no use of this software other than that for which it was
 * delivered.  This is an unpublished copyrighted work of Digi International
 * Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
 * prohibited.
 * 
 * Restricted Rights Legend
 *
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7031 or
 * subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 * Restricted Rights at 48 CFR 52.227-19, as applicable.
 *
 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 *
 ***************************************************************************
 *
 * @Descr: WatchDog Class
 *
 * @History:
 *	07/10/09:	aramos      initial version.
 *  08/12/09:   aramos      code revision.
 *
 ***************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Digi.Common;

/*! \package Digi.Drivers
 */
/// <summary>
/// The Digi.Drivers includes the classes that implement the different Digi Drivers (GPIO, I2C, SPI...)
/// </summary>
namespace Digi.Drivers
{    
    /*! \class WatchDog
     */
    /// <summary>
    /// WatchDog class
    /// This class manage create WatchDogs
    /// </summary>
    public class WatchDog
    {
        /*! \enum WatchDogAction
        */
        /// <summary>
        /// WatchDog Action enumeration
        /// Enumeration of the possible actions to take
        /// </summary>
        /// <example>
        /// <code>
        /// // Use of the constants
        /// WatchDogAction.NoDefaultAction
        /// WatchDogAction.KillProcess
        /// WatchDogAction.ResetDevice</code>
        /// </example>
        public enum WatchDogAction : uint
        {
            NoDefaultAction = 0,
            KillProcess = 1,
            ResetDevice = 2
        }

        //Global const
        private const int INVALID_HANDLE_VALUE = -1;
        private const int RESERVED = 0;
        private const int TIME_TO_WAIT = 0;
        private const int HAL_REBOOT_PARAM = 0;
        private const int FLAGS = 0;

        //dll import
        [System.Runtime.InteropServices.DllImport("coredll.dll")]
        private static extern IntPtr CreateWatchDogTimer(
                                        string lpFileName,
                                        uint dwPeriod,
                                        uint dwWait,
                                        uint dwDfltAction,
                                        uint dwParam,
                                        uint dwFlags);

        [System.Runtime.InteropServices.DllImport("coredll.dll")]
        private static extern bool StartWatchDogTimer(System.IntPtr h,
                                        uint dwFlags);

        [System.Runtime.InteropServices.DllImport("coredll.dll")]
        private static extern bool RefreshWatchDogTimer(System.IntPtr h,
                                        uint dwFlags);

        //Handle
        private IntPtr hWD = (IntPtr)(-1);

        /*! \fn WatchDog(uint TimeOut, uint Action)
         */
        /// <summary>
        /// Constructor, need TimeOut and default action
        /// </summary>
        /// <param name="TimeOut">TimeOut to be configured</param>
        /// <param name="Action">The Action to be executed</param>
        public WatchDog(uint TimeOut, uint Action)
        {
            if ((Action < (uint)WatchDogAction.NoDefaultAction) || (Action > (uint)WatchDogAction.ResetDevice))
                throw new ArgumentException();
            hWD = CreateWatchDogTimer("WD", TimeOut, TIME_TO_WAIT, Action, HAL_REBOOT_PARAM, RESERVED);
            if (hWD == (IntPtr)INVALID_HANDLE_VALUE)
                throw new Exception("[WatchDog]CreateWatchDogTimer failed");
        }

        /*! \public bool Start()
         */
        /// <summary>
        /// Method that starts the watchdog 
        /// </summary>
        /// <returns>true indicates success</returns>
        public bool Start()
        {
            return (StartWatchDogTimer(hWD, FLAGS));
        }

        /*! \public bool Refresh()
         */
        /// <summary>
        /// Method that refreshes the watchdog 
        /// </summary>
        /// <returns>true indicates success</returns>
        public bool Refresh()
        {
            return (RefreshWatchDogTimer(hWD, FLAGS));
        }
    }
}