//------------------------------------------------------------------------------
// Copyright (C) 2008 Invensys Systems Inc.  All rights reserved.
// 
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//------------------------------------------------------------------------------

using System;
using System.Runtime.InteropServices;
using System.Collections;
using ArchestrA.Core;
using ArchestrA.Toolkit;

namespace ArchestrA.Toolkit.Watchdog
{
    [Guid("886e73ad-ddb7-45ca-8ca2-e652e1e9bafd")]
    /// <summary>
    /// Summary description for Watchdog
    /// </summary>
    public class WatchdogRuntime : RuntimeBase
    {
        #region Attributes - Toolkit generated code
        // The following C# properties have been defined to simplify access to
        // attribute values - do not modify the contents of this region with
        // the code editor.
        private CMxBoolean Timeout
        {
            get { return InternalReferenceOnly.Timeout; }
            set { InternalReferenceOnly.Timeout.Set(value); }
        }

        private CMxElapsedTime TimeSinceChange
        {
            get { return InternalReferenceOnly.TimeSinceChange; }
            set { InternalReferenceOnly.TimeSinceChange.Set(value); }
        }

        private CMxElapsedTime Timeout_Limit
        {
            get { return InternalReferenceOnly.Timeout_Limit; }
            set { InternalReferenceOnly.Timeout_Limit.Set(value); }
        }



        public __InputPrimitive1 InputPrimitive1 = null;

        public class __InputPrimitive1 : InputPrimBase
        {
            protected override void Initialize(SupportWrapper _Wrapper)
            {
                if (_Value == null) { _Value = new CMxVariant(Wrapper, "MonitoredBit.Value"); }
                if (_DataType == null) { _DataType = new CMxDataType(Wrapper, "MonitoredBit.DataType"); }

                attrId = _Value.Attribute.shAttributeId;
                primId = _Value.Attribute.shPrimitiveId;
                dataType = _DataType.Value;

                base.Initialize(Wrapper);
            }

            public SupportWrapper Wrapper = new SupportWrapper();

            private CMxVariant _Value = null;

            public CMxVariant Value
            {
                get { if (_Value == null) { _Value = new CMxVariant(Wrapper, "MonitoredBit.Value"); } return _Value; }
                set { if (_Value == null) { _Value = new CMxVariant(Wrapper, "MonitoredBit.Value"); } _Value.Set(value); }
            }

            private CMxStatus _ReadStatus = null;

            public CMxStatus ReadStatus
            {
                get { if (_ReadStatus == null) { _ReadStatus = new CMxStatus(Wrapper, "MonitoredBit.ReadStatus"); } return _ReadStatus; }
                set { if (_ReadStatus == null) { _ReadStatus = new CMxStatus(Wrapper, "MonitoredBit.ReadStatus"); } _ReadStatus.Set(value); }
            }

            private CMxReference _InputSource = null;

            public CMxReference InputSource
            {
                get { if (_InputSource == null) { _InputSource = new CMxReference(Wrapper, "MonitoredBit.InputSource"); } return _InputSource; }
                set { if (_InputSource == null) { _InputSource = new CMxReference(Wrapper, "MonitoredBit.InputSource"); } _InputSource.Set(value); }
            }

            private CMxDataType _DataType = null;

            public CMxDataType DataType
            {
                get { if (_DataType == null) { _DataType = new CMxDataType(Wrapper, "MonitoredBit.DataType"); } return _DataType; }
            }

            public AoAWrapper AoA = null;

            public void SuspendUpdatesList()
            {
                if (AoA == null) { AoA = new AoAWrapper(Wrapper, new string[] { "MonitoredBit.Value" }); } AoA.SuspendUpdatesList();
            }

            public void ActivateUpdatesList()
            {
                if (AoA == null) { AoA = new AoAWrapper(Wrapper, new string[] { "MonitoredBit.Value" }); } AoA.ActivateUpdatesList();
            }

            public __InputPrimitive1(AObjectBase baseClass)
            {
                Wrapper.baseClass = baseClass;
            }

        }

        #endregion Attributes

        #region Internal Reference Only
        //Toolkit code required to access the attributes declared in the Object Class
        private WatchDog InternalReferenceOnly = null;
        #endregion Internal Reference Only

        #region Declarations
        //Declare Runtime Class Variables here.
        //Variables declared in this region are available to all methods 
        //in the Runtime Class.
        DateTime m_TimeOfLastChange;
        bool m_LastInputValue;


        #endregion Declarations


        public WatchdogRuntime()
        {
            InternalReferenceOnly = new WatchDog();
            this.AObjectInstance = InternalReferenceOnly;

            #region Runtime Event Registration - Toolkit generated code
            // Required region for Runtime Events - do not modify 
            // the contents of this region with the code editor.
            base.RuntimeGetStatusDesc += new RuntimeGetStatusDescDelegate(WatchdogRuntime_RuntimeGetStatusDesc);
            base.RuntimeSetScanState += new RuntimeSetScanStateDelegate(Watchdog_RuntimeSetScanState);
            base.RuntimeExecute += new RuntimeExecuteDelegate(Watchdog_RuntimeExecute);
            base.RuntimeShutdown += new RuntimeShutdownDelegate(Watchdog_RuntimeShutdown);
            base.RuntimeStartup += new RuntimeStartupDelegate(Watchdog_RuntimeStartup);
            base.RuntimeDynamic += new RuntimeDynamicSetHandlerDelegate(WatchdogRuntime_RuntimeDynamic);
            base.RuntimeInitialize += new RuntimeInitializeDelegate(WatchdogRuntime_RuntimeInitialize);
            #endregion Runtime Event Registration

            #region Runtime Set Handler Registration – Toolkit generated code
            // Required method for Runtime SetHandlers.  
            // Changes made using the code editor will appear in the Toolkit Editor.
            // 
            // WARNING: Changes made to this region will result in a Shape Change.

            //	TODO: Runtime SetHandler registration
            this.RegisterRuntimeSetHandler("Timeout.Limit", new RuntimeSetHandlerDelegate(Timeout_LimitSetHandler));
            #endregion Runtime Set Handler Registration

            #region Primitive Wrapper Initialization - Toolkit generated code
            InputPrimitive1 = new __InputPrimitive1(this);
            #endregion Primitive Wrapper Initialization

            #region Primitive Advise only Activate Registration - Toolkit generated code
            #endregion Primitive Advise only Activate Initialization
        }

        private void WatchdogRuntime_RuntimeInitialize(object sender)
        {
            //------------------------------------------------------------------------------
            //  TODO: Runtime - Initialize
            //
            //  Do not read or write attribute values of this primitive during Initialize
            //------------------------------------------------------------------------------
        }

        private void Watchdog_RuntimeExecute(object sender)
        {
            //------------------------------------------------------------------------------
            //  TODO: Runtime - Execute
            //
            //  This is where the main logic of the object periodically executes when
            //  the object is on scan.
            //
            //  Read or write the attributes of this primitive using the generated 
            //  properties (Value, Quality).
            //------------------------------------------------------------------------------
            #region Example code
            //          // The lines below both increment the value of the attribute "Attribute1" by 1
            //          Example_001 ++;  
            //          Example_001 = Example_001 + 1;
            //
            //          //Example_001 quality is set to Bad on Condition_001 being true.
            //          Example_001.Quality = (Condition_001 ?  DataQuality.DataQualityBad : DataQuality.DataQualityGood);
            //
            //          // The attribute "ElapsedTime" contains the time elapsed since the last reset
            //          ElapsedTime = GetScanTime() - TimeOfLastReset;
            //
            //          // Increment the 3rd element of an array
            //          FloatArray[3] ++; 
            //
            //          // Increment all the elements of an array
            //          for( short counter = 1; counter <= FloatArray.Length; counter ++)
            //          {
            //            FloatArray[counter] ++;
            //          }
            #endregion

            bool CurrentBitValue = (bool)InputPrimitive1.GetValue();
            DateTime Now = GetScanTime();

            //Cache the current time internally if the monitored bit has just changed
            if (CurrentBitValue != m_LastInputValue)
            {
                m_TimeOfLastChange = Now; //remember the current time
            }
            m_LastInputValue = CurrentBitValue;

            //Now update the calculated attributes: "TimeSinceChange" and "Timeout.Condition"
            TimeSinceChange = Now - m_TimeOfLastChange;
            Timeout = TimeSinceChange > Timeout_Limit;
        }

        private void Watchdog_RuntimeShutdown(object sender)
        {
            //------------------------------------------------------------------------------
            //  TODO: Runtime Event - Shutdown
            //
            //  Clean up dynamic allocation, release open resources, etc.
            //------------------------------------------------------------------------------

            // Activate marked attributes before shutting down
            AdviseOnlyActivateAttributes();
        }

        private void Watchdog_RuntimeStartup(object sender, RuntimeStartupEventArgs e)
        {
            //------------------------------------------------------------------------------
            //  TODO: Runtime Event - Startup
            //
            //  Cache attributes. Cache Primitive IDs of other known primitives.
            //------------------------------------------------------------------------------

            // RestoreDynamicAttributes will recreate the Dynamic Attributes and restore the check pointed 
            // values during failover startup. The Failover Support for Dynamic Attributes option must
            // be enabled via the Object Editor to support this function. To maintain the 
            // Dynamic Attribute values the CheckpointDynamicAttributeData function must be called
            // when Dynamic Attribute values are modified (refer to the Dynamic Attribute Set Handler).

            //RestoreDynamicAttributes();

            m_TimeOfLastChange = GetScanTime();

            // Execute offscan code to initialize the object in its offscan state.
            SetScanState(false);

            // Suspend marked attributes at startup
            AdviseOnlySuspendAttributes();

        }

        private void AdviseOnlySuspendAttributes()
        {
            // Required Method for Advise only Active.
            // Do not modify this method via the code editor.
            //
            // WARNING: Changes made to this method will be overwritten by the code generator.

            if (AdviseOnlyActiveEnabled)
            {
            }
        }

        private void AdviseOnlyActivateAttributes()
        {
            // Required Method for Advise only Active.
            // Do not modify this method via the code editor.
            //
            // WARNING: Changes made to this method will be overwritten by the code generator.

            if (AdviseOnlyActiveEnabled)
            {
            }
        }

        private void Watchdog_RuntimeSetScanState(object sender, RuntimeSetScanStateEventArgs e)
        {
            //------------------------------------------------------------------------------
            //  TODO: Runtime Event - SetScanState
            //
            //  Perform actions when the object goes on or off scan.
            //------------------------------------------------------------------------------
        }

        private void WatchdogRuntime_RuntimeGetStatusDesc(object sender, ref RuntimeGetStatusDescEventArgs e)
        {
            //------------------------------------------------------------------------------
            //  TODO: Runtime Event - GetStatusDesc
            //
            //  This routine provides a String for an error code when a client requests it.
            //  By default this method looks for an entry in the dictionary that has the 
            //  DetailedErrorCode as the PhraseID.
            //
            //  You need to change this implmentation if you want to provide embedded values 
            //  within your messages, or you want to use string PhraseIDs instead of integer 
            //  PhraseIDs.
            //------------------------------------------------------------------------------

            switch (e.detailedErrorCode)
            {
                case 10000:
                    e.status = GetText("Timeout.Limit must be a positive number.");
                    break;
                default:
                    e.status = GetText((int)e.detailedErrorCode);
                    break;
            }
        }

        private void WatchdogRuntime_RuntimeDynamic(object sender, ref RuntimeSetHandlerEventArgs e)
        {

            string attrName = Get(e.attributeHandle.shAttributeId, e.attributeHandle.shPrimitiveId, EATTRIBUTEPROPERTY.idxAttribPropName);

            //------------------------------------------------------------------------------
            //	TODO: Runtime Event - Dynamic Set Handler
            //
            //  Implement set handler code for any dynamic attributes you create with set handlers  
            //------------------------------------------------------------------------------

            // CheckpointDynamicAttributeData will update the checkpoint values for all Dynamic Attributes. 
            // To recreate Dynamic Attributes and restore Dynamic Attribute values the RestoreDynamicAttributes 
            // function must be called when starting up from failover (refer to the Startup method).

            //CheckpointDynamicAttributeData();

            #region Example
            // if (attrName == "MyDynamic")
            // {
            //     if (e.Value > 10)
            //     {
            //         LogWarning(string.Format("value for {0} must be less or equal to 10", attrName));
            //     }
            //     else
            //     {
            //         SetValue(attrName, e.Value);
            //     }
            //
            //    
            //     return;
            // }   
            #endregion

            // if unhandled a warning is shown as a reminder
            SetValue(e.attributeHandle.shAttributeId, e.attributeHandle.shPrimitiveId, e.Value);
            LogWarning(string.Format("Uknown set handler for attribute '{0}'", attrName));

        }

        private void Timeout_LimitSetHandler(object sender, ref RuntimeSetHandlerEventArgs e)
        {

            if (e.Value < 0)
            {
                e.status.detail = 10000;
                e.status.Category = MxStatusCategory.MxCategoryConfigurationError;
                return;
            }

            Timeout_Limit.SetHandlerValue = e;
        }

        //TODO: Runtime SetHandler declaration
        //private void Example_001SetHandler(object sender, ref RuntimeSetHandlerEventArgs e)
        //{
        //    Example_001 = e.Value;
        //}
    }
}

