namespace EventSourceComplexTypesApp
{
    using System;
    using System.Diagnostics.Tracing;

    [EventSource(Name = "EventSourceWithComplexType")]
    public sealed class EventSourceWithComplexType : EventSource
    {
        #region Inner Types

        public class Keywords
        {
            public const EventKeywords Creation = (EventKeywords)0x0001; // 1
            public const EventKeywords AdmissionApproved = (EventKeywords)0x0002; // 2
            public const EventKeywords FeeDeposited =  (EventKeywords)0x0004; // 4
            public const EventKeywords TransferCreditHours =  (EventKeywords)0x0008; // 8
            public const EventKeywords Emergency = (EventKeywords)0x0010; // 16
            public const EventKeywords Attendance = (EventKeywords)0x0100; // 32
            public const EventKeywords InterKidsIssues = (EventKeywords)0x1000; // 64
        }

        #endregion Inner Types

        #region Private Fields

        private static readonly Lazy<EventSourceWithComplexType>  Instance =
            new Lazy<EventSourceWithComplexType>(() => new EventSourceWithComplexType());

        #endregion Private Fields

        #region Private Constructor

        private EventSourceWithComplexType() { }

        #endregion Private Constructor

        #region Public Properties

        public static EventSourceWithComplexType Log
        {
            get { return Instance.Value; }
        }

        #endregion Public Properties

        #region Non-Event Public Methods

        [NonEvent]
        public void StudentCreated(Student student)
        {
            StudentCreatedCore(student.StudentId, student.StudentName, student.StudentAge);
        }

        [NonEvent]
        public void AdmissionApproved(Student student)
        {
            StudentAdmittedCore(student.StudentId, student.StudentName);
        }

        [NonEvent]
        public void FeeDeposited(Student student, double amount)
        {
            FeeDepositedCore(student.StudentId, student.StudentName, amount);
        }

        [NonEvent]
        public void TransferCreditHours(Student student)
        {
            TransferCreditHoursCore(student.StudentId);
        }

        [NonEvent]
        public void StudentEmergency(Student student)
        {
            StudentEmergencyCore(student.StudentId, student.StudentName, "911");
        }

        [NonEvent]
        public void StudentTransportIssue(Student student)
        {
            StudentTransportIssueCore(student.StudentId, student.StudentName);
        }

        [NonEvent]
        public void StudentAttendedClass(Student student)
        {
            StudentAttendedClassCore(student.StudentId);
        }

        [NonEvent]
        public void StudentGotIntoFight(Student student)
        {
            StudentGotIntoFightCore(student.StudentId);
        }

        #endregion Non-Event Public Methods

        #region Event Private Methods

        [Event(
            1, 
            Message = "Student Id: {0}, Name: {1}, Age:{2}", 
            Level = EventLevel.LogAlways, 
            Version = 2,
            Keywords = Keywords.Creation)]
        private void StudentCreatedCore(int studentId, string studentName, int studentAge)
        {
            WriteEvent(1, studentId, studentName, studentAge);
        }

        [Event(
            2, 
            Message = "Student Id: {0}, Name: {1}", 
            Level = EventLevel.Informational,
            Version = 1,
            Keywords = Keywords.AdmissionApproved)]
        private void StudentAdmittedCore(int studentId, string studentName)
        {
            WriteEvent(2, studentId, studentName);
        }

        [Event(
            3,
            Message = "Student Id: {0}, Name: {1}, Age:{2}",
            Level = EventLevel.Informational,
            Version = 1,
            Keywords = Keywords.FeeDeposited)]
        private void FeeDepositedCore(int studentId, string studentName, double feeAmount)
        {
            WriteEvent(3, studentId, studentName, feeAmount);
        }

        [Event(
            4,
            Message = "Student Id: {0}",
            Level = EventLevel.Informational,
            Version = 1,
            Keywords = Keywords.TransferCreditHours)]
        private void TransferCreditHoursCore(int studentId)
        {
            WriteEvent(4, studentId);
        }

        [Event(
            5,
            Message = "Student Id: {0}, Emergency Number: {2}",
            Level = EventLevel.Critical,
            Version = 1,
            Keywords = Keywords.Emergency)]
        private void StudentEmergencyCore(int studentId, string studentName, string emergencyNumber)
        {
            WriteEvent(5, studentId, studentName, emergencyNumber);
        }

        [Event(
            6,
            Message = "Student Id: {0}, StudentName: {1}",
            Level = EventLevel.Error,
            Version = 1,
            Keywords = Keywords.Emergency)]
        private void StudentTransportIssueCore(int studentId, string studentName)
        {
            WriteEvent(6, studentId, studentName);
        }

        [Event(
            7,
            Message = "Student Id: {0}",
            Level = EventLevel.Verbose,
            Version = 1,
            Keywords = Keywords.Attendance)]
        private void StudentAttendedClassCore(int studentId)
        {
            WriteEvent(7, studentId);
        }

        [Event(
            8,
            Message = "Student Id: {0}",
            Level = EventLevel.Warning,
            Version = 1,
            Keywords = Keywords.InterKidsIssues)]
        private void StudentGotIntoFightCore(int studentId)
        {
            WriteEvent(8, studentId);
        }

        #endregion Event Private Methods
    }
}