//******************************************************************************//
// ErrorLoggerPacketsParser.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY  METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using GalaSoft.MvvmLight.Messaging;
using Raytheon.LogDashboard.Model;
using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading;

namespace Raytheon.LogDashboard.Parsers
{
    /// <summary>
    /// \\\\.\\mailslot\\TsdcSystemSwErrorMailSlot
    /// \\\\.\\mailslot\\TsdcSystemSwErrorMailSlot64
    /// </summary>
    public class ErrorLoggerPacketsParser : PacketsParser
    {
        private MailslotServer mailslotServer { get; set; }
        private Mutex _mutex;

        public ErrorLoggerPacketsParser(string name, bool isAutoSave)
            : base(name, isAutoSave)
        { }

        public ErrorLoggerPacketsParser(string name, string address, bool isAutoSave)
            : this(name, isAutoSave)
        {
            Address = address;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override LogMessage GetLog()
        {
            string msg = mailslotServer.GetNextMessage();

            if(msg != null)
            {
                return ParseString(msg);
            }

            return null;
        }

        private LogMessage ParseString(string inputString)
        {
            int index = 0;
            string[] fields = new string[4];
            for(int i = 0; i < 3; i++)
            {
                int nextIndex = inputString.IndexOf(',', index);
                if(nextIndex == -1)
                {
                    throw new ArgumentException("Input string is not in the correct format.");
                }
                fields[i] = inputString.Substring(index, nextIndex - index).Trim();
                index = nextIndex + 1;
            }
            fields[3] = inputString.Substring(index).Trim();

            LogMessage msg = new LogMessage
            {
                Logger = Name,
                Address = Address,
                Time = ParseDate(fields[1]),
                Level = GetLevel(fields[2]),
                Message = fields[3]
            };

            if(IsAutoSave && msg != null)
            {
                Messenger.Default.Send(msg, "PersistLogMessage");
            }

            return msg;
        }

        private DateTime ParseDate(string data)
        {
            if(DateTime.TryParseExact(data, "ddd MMM dd HH:mm:ss yyyy fff'ms'", null, DateTimeStyles.AssumeLocal, out DateTime dateTime))
            {
                return dateTime;
            }
            else
            {
                return DateTime.Now;
            }
        }

        private DashboardLogLevel GetLevel(string level)
        {
            switch(level)
            {
                case "LOG_INFO_VERBOSE":
                    return DashboardLogLevel.Trace;
                case "LOG_INFORMATION":
                    return DashboardLogLevel.Info;
                case "LOG_WARNING":
                    return DashboardLogLevel.Warn;
                case "LOG_DEBUG":
                    return DashboardLogLevel.Debug;
                case "LOG_ERROR":
                    return DashboardLogLevel.Error;

                default:
                    return DashboardLogLevel.Error;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override bool Init()
        {
            base.Init();

            string strMutex = !string.IsNullOrEmpty(Address) && Address.Trim().EndsWith("64") ? 
                "ErrorLoggerMutex_F1BB29A5-0AFC-45e9-A725-C302DF7EB3CF_64" : 
                "ErrorLoggerMutex_F1BB29A5-0AFC-45e9-A725-C302DF7EB3CF";

            _mutex = new Mutex(true, strMutex, out bool createdNew);

            if(!createdNew)
            {
                Process[] errorLoggerProcesses = Process.GetProcessesByName("ErrorLogger");
                if(errorLoggerProcesses.Any())
                {
                    Process er = errorLoggerProcesses.First();

                    Messenger.Default.Send("Detected ErrorLogger instance running. Please close ErrorLogger or disable the Error Logger receiver.", "DisplayCustomMessage");

                    _mutex = new Mutex(true, strMutex, out createdNew);
                }
            }

            if(!createdNew)
            {
                Logger.Error($"Error initializing Mailslot {Address}\nOnly one instance of ErrorLogger is allowed");

                IsInitialized = false;
                return false;
            }

            try
            {
                mailslotServer = new MailslotServer(Address);
            }
            catch(Exception ex)
            {
                Logger.Error($"Error initializing Mailslot {Address}\n{ex.Message}");

                IsInitialized = false;
                return false;
            }

            IsInitialized = true;
            return IsInitialized;
        }

        /// <summary>
        /// 
        /// </summary>
        public override void Dispose()
        {
            base.Dispose();

            mailslotServer?.Dispose();

            _mutex?.Dispose();
        }
    }
}
