/// <summary>
        /// Routine to create a complex event frame for use in testing.
        /// </summary>
        /// <param name="db">The AF Database where the event frame should be created.</param>
        /// <param name="efData">Data used to create the event frame.</param>
        /// <returns>Fully created event frame object is returned.</returns>
        /// <remarks>
        /// The Event Frame created in this routine can be verified using the FullEventFrameVerify() routine.
        /// </remarks>
        private AFEventFrame FullEventFrameCreate(AFDatabase db, EventFrameTestConfiguration efData)
        {
            var attrCat = db.AttributeCategories[efData.AttributeCategoryName];

            if (attrCat == null)
            {
                attrCat = db.AttributeCategories.Add(efData.AttributeCategoryName);
            }
            var elemCat = db.ElementCategories[efData.ElementCategoryName];

            if (elemCat == null)
            {
                elemCat = db.ElementCategories.Add(efData.ElementCategoryName);
            }

            var elem = db.Elements[efData.EventFrameElementName];

            if (elem == null)
            {
                elem = db.Elements.Add(efData.EventFrameElementName);
            }
            if (elem.IsDirty)
            {
                elem.ApplyChanges();
            }

            var newEventFrame = new AFEventFrame(db, efData.Name);

            var attr1 = newEventFrame.Attributes.Add(efData.Attribute1Name);

            attr1.Categories.Add(attrCat);
            attr1.Type = typeof(AFFile);
            var attr2 = newEventFrame.Attributes.Add(efData.Attribute2Name);

            attr2.Type = typeof(double);
            attr2.SetValue(efData.Attribute2Value, null);
            var attr3 = newEventFrame.Attributes.Add(efData.Attribute3Name);

            attr3.DataReferencePlugIn = db.PISystem.DataReferencePlugIns[efData.DataReferencePlugInName];
            attr3.ConfigString        = efData.DataReferenceConfigString;

            newEventFrame.Categories.Add(elemCat);
            newEventFrame.EventFrames.Add(efData.ChildEventFrame);
            newEventFrame.ExtendedProperties.Add(efData.ExtPropKey, efData.ExtPropValue);
            newEventFrame.ReferencedElements.Add(elem);

            var ann = new AFAnnotation(newEventFrame)
            {
                Name  = efData.AnnotationName,
                Value = efData.AnnotationValue,
            };

            ann.Save();

            return(newEventFrame);
        }
        public void EventFrameTest()
        {
            AFDatabase db = Fixture.AFDatabase;

            const string EventFrameName   = "OSIsoftTests_AF_InitEF#1A";
            const string EventFrameRename = "OSIsoftTests_AF_EventFrameTest_NewName";

            var testData = new EventFrameTestConfiguration(EventFrameName);

            try
            {
                Output.WriteLine($"Create Event Frame [{EventFrameName}].");
                var evtfr1 = FullEventFrameCreate(db, testData);
                db.CheckIn();

                Output.WriteLine("Confirm Event Frame created and found.");
                db     = Fixture.ReconnectToDB(); // This operation clears AFSDK cache and assures retrieval from AF server
                evtfr1 = AFEventFrame.FindEventFrame(db.PISystem, evtfr1.ID);
                FullEventFrameVerify(db, evtfr1.ID, testData, Output);

                Output.WriteLine($"Rename Event Frame to [{EventFrameRename}].");
                evtfr1.Name = EventFrameRename;
                db.CheckIn();

                // Update test data with new name
                testData.Name = EventFrameRename;

                Output.WriteLine($"Verify Event Frame [{EventFrameRename}] found on reread.");
                db     = Fixture.ReconnectToDB();
                evtfr1 = AFEventFrame.FindEventFrame(db.PISystem, evtfr1.ID);
                FullEventFrameVerify(db, evtfr1.ID, testData, Output);

                Output.WriteLine($"Delete Event Frame [{EventFrameRename}].");
                evtfr1.Delete();
                db.CheckIn();

                Output.WriteLine($"Confirm Event Frame deleted.");
                db = Fixture.ReconnectToDB();
                var deletedEFSearch = AFEventFrame.FindEventFrame(db.PISystem, evtfr1.ID);
                Assert.True(deletedEFSearch == null, $"Event Frame [{EventFrameRename}] was not deleted as expected.");
            }
            finally
            {
                Fixture.RemoveElementIfExists(testData.EventFrameElementName, Output);
            }
        }
        /// <summary>
        /// Verifies a complex event frame object.
        /// </summary>
        /// <param name="db">The AF Database that contains the event frame being verified.</param>
        /// <param name="evtfrmId">ID (GUID) of the event frame to be verified.</param>
        /// <param name="expData">Expected Data to check the event frame.</param>
        /// <param name="output">The output logger used for writing messages.</param>
        /// <remarks>
        /// This routine is used to verify event frames created using the FullEventFrameCreate() routine.
        /// </remarks>
        private void FullEventFrameVerify(AFDatabase db, Guid evtfrmId, EventFrameTestConfiguration expData, ITestOutputHelper output)
        {
            var eventFrameFound = AFEventFrame.FindEventFrame(db.PISystem, evtfrmId);

            Assert.True(eventFrameFound != null, $"Unable to find Event Frame [{expData.Name}] with ID [{evtfrmId}].");
            string actEFName = eventFrameFound.Name;

            Assert.True(actEFName.Equals(expData.Name, StringComparison.OrdinalIgnoreCase),
                        $"Element Template found with ID [{evtfrmId}] had name [{actEFName}], expected [{expData.Name}].");

            Assert.True(db.AttributeCategories[expData.AttributeCategoryName] != null,
                        $"Check Failed. Attribute Category [{expData.AttributeCategoryName}] not found.");
            Assert.True(db.ElementCategories[expData.ElementCategoryName] != null,
                        $"Check Failed. Element Category [{expData.ElementCategoryName}] not found.");

            output.WriteLine("Check Event Frame Attributes.");
            int actualAttributeCount = eventFrameFound.Attributes.Count;

            Assert.True(actualAttributeCount == 3, $"Event Frame Attribute Count Failed. Actual {actualAttributeCount}, expected 3.");
            var attr1 = eventFrameFound.Attributes[expData.Attribute1Name];

            Assert.True(attr1 != null, $"Event Frame [{expData.Name}] did not have attribute [{expData.Attribute1Name}] as expected.");
            Assert.True(attr1.Categories[expData.AttributeCategoryName] != null,
                        $"Attribute [{expData.Attribute1Name}] in Event Frame [{expData.Name}]" +
                        $" did not have category [{expData.AttributeCategoryName}] as expected.");

            var attr2 = eventFrameFound.Attributes[expData.Attribute2Name];

            Assert.True(attr2 != null, $"Event Frame [{expData.Name}] did not have attribute [{expData.Attribute2Name}] as expected.");
            Assert.True(expData.Attribute2Value == attr2.GetValue().ValueAsDouble(),
                        $"Event Frame [{expData.Name}] attribute [{expData.Attribute2Name}] data was" +
                        $" [{attr2.GetValue().ValueAsDouble()}], expected [{expData.Attribute2Value}].");

            var attr3 = eventFrameFound.Attributes[expData.Attribute3Name];

            Assert.True(attr3 != null, $"Event Frame [{expData.Name}] did not have attribute [{expData.Attribute3Name}] as expected.");
            Assert.True(attr3.DataReferencePlugIn == db.PISystem.DataReferencePlugIns[expData.DataReferencePlugInName],
                        $"Attribute [{expData.Attribute3Name}] in Event Frame [{expData.Name}]" +
                        $" did not have data reference PlugIn [{expData.DataReferencePlugInName}] as expected.");
            Assert.True(attr3.ConfigString == expData.DataReferenceConfigString,
                        $"Attribute [{expData.Attribute3Name}] in Event Frame [{expData.Name}] data reference ConfigString was" +
                        $" [{attr3.ConfigString}], expected [{expData.DataReferenceConfigString}].");

            output.WriteLine("Check Event Frame Categories.");
            int       actualEventFrameCategoriesCount   = eventFrameFound.Categories.Count;
            const int ExpectedEventFrameCategoriesCount = 1;

            Assert.True(actualEventFrameCategoriesCount == ExpectedEventFrameCategoriesCount,
                        $"Category Count in Event Frame [{expData.Name}] was " +
                        $"{actualEventFrameCategoriesCount}, expected {ExpectedEventFrameCategoriesCount}.");
            Assert.True(eventFrameFound.Categories[expData.ElementCategoryName] != null,
                        $"Category [{expData.ElementCategoryName}] not found in Event Frame [{expData.Name}] as expected.");

            output.WriteLine("Check Child Event Frames.");
            int       actualEventFrameCount   = eventFrameFound.EventFrames.Count;
            const int ExpectedEventFrameCount = 1;

            Assert.True(actualEventFrameCount == ExpectedEventFrameCount,
                        $"Count in Event Frame [{expData.Name}] was {actualEventFrameCount}, expected {ExpectedEventFrameCount}.");
            Assert.True(eventFrameFound.EventFrames[expData.ChildEventFrame] != null,
                        $"Child Event Frame [{expData.ChildEventFrame}] not found in Event Frame [{expData.Name}] as expected.");

            output.WriteLine("Check Extended properties.");
            int       actualExtPropertiesCount   = eventFrameFound.ExtendedProperties.Count;
            const int ExpectedExtPropertiesCount = 1;

            Assert.True(actualExtPropertiesCount == ExpectedExtPropertiesCount,
                        $"ExtendedProperties Count in Event Frame [{expData.Name}] was {actualExtPropertiesCount}, expected {ExpectedExtPropertiesCount}.");
            string actualExtPropValue = eventFrameFound.ExtendedProperties[expData.ExtPropKey].ToString();

            Assert.True(actualExtPropValue.Equals(expData.ExtPropValue, StringComparison.OrdinalIgnoreCase),
                        $"ExtendedProperty Key [{expData.ExtPropKey}] in Event Frame [{expData.Name}]" +
                        $" had Value [{actualExtPropValue}], expected [{expData.ExtPropValue}].");

            output.WriteLine("Check Referenced Element.");
            int       actualRefdElementsCount   = eventFrameFound.ReferencedElements.Count;
            const int ExpectedRefdElementsCount = 1;

            Assert.True(actualRefdElementsCount == ExpectedRefdElementsCount,
                        $"Referenced Element Count in Event Frame [{expData.Name}] was {actualRefdElementsCount}, expected {ExpectedRefdElementsCount}.");
            Assert.True(actualExtPropValue.Equals(expData.ExtPropValue, StringComparison.OrdinalIgnoreCase),
                        $"Referenced Element [{expData.EventFrameElementName}] not found in Event Frame [{expData.Name}] as expected.");

            output.WriteLine("Check Event Frame Annotations.");
            var       annotations              = eventFrameFound.GetAnnotations();
            int       actualAnnotationsCount   = annotations.Count;
            const int ExpectedAnnotationsCount = 1;

            Assert.True(actualAnnotationsCount == ExpectedAnnotationsCount,
                        $"Annotations Count in Event Frame [{expData.Name}] was {actualAnnotationsCount}, expected {ExpectedAnnotationsCount}.");
            Assert.True(annotations[0].Name.Equals(expData.AnnotationName, StringComparison.OrdinalIgnoreCase),
                        $"Annotations[0] Name in Event Frame [{expData.Name}] was [{annotations[0].Name}], expected [{expData.AnnotationName}].");
            Assert.True(annotations[0].Value.ToString().Equals(expData.AnnotationValue, StringComparison.OrdinalIgnoreCase),
                        $"Annotations[0] Value in Event Frame [{expData.Name}] was [{annotations[0].Value.ToString()}], expected [{expData.AnnotationValue}].");
        }