///
/// Nanotec Nanolib example
/// Copyright (C) Nanotec GmbH & Co. KG - All Rights Reserved
///
/// This product includes software developed by the
/// Nanotec GmbH & Co. KG (http://www.nanotec.com/).
///
/// The Nanolib interface headers and the examples source code provided are 
/// licensed under the Creative Commons Attribution 4.0 Internaltional License. 
/// To view a copy of this license, 
/// visit https://creativecommons.org/licenses/by/4.0/ or send a letter to 
/// Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
///
/// The parts of the library provided in binary format are licensed under 
/// the Creative Commons Attribution-NoDerivatives 4.0 International License. 
/// To view a copy of this license, 
/// visit http://creativecommons.org/licenses/by-nd/4.0/ or send a letter to 
/// Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
///
/// <file_name>LoggingCallbackExample.cs</file_name>
///
/// <summary>Definition of logging callback class</summary>
///
/// <date>29-10-2024</date>
///
/// <author>Michael Milbradt<author>
///

using Nlc;

namespace NanolibExample
{
    /// <summary>
    /// Implementation class of NlcLoggingCallback, handling the logging callback.
    /// </summary>
    public class LoggingCallbackExample : NlcLoggingCallback
    {
        /// <summary>
        /// Track wether dispose has been called
        /// </summary>
        private bool _disposed;

        /// <summary>
        /// Nanolib accessor object, needed during dispose
        /// </summary>
        private readonly Nlc.NanoLibAccessor _accessor = Nanolib.getNanoLibAccessor();

        /// <summary>
        /// Gets called whenever a log output is made.
        /// </summary>
        /// <param name="payloadStr">The complete logging string.</param>
        /// <param name="formattedStr">The formatted logging string.</param>
        /// <param name="loggerName">Name of the logger.</param>
        /// <param name="logLevel">Log level.</param>
        /// <param name="timeSinceEpoch">Timestamp in ms (since epoch).</param>
        /// <param name="threadId">Thread ID of logging call.</param>
        public override void callback(string payload_str, string formatted_str, string logger_name, uint log_level, ulong time_since_epoch, uint thread_id)
        {
            string formattedString = formatted_str;
            int pos;

            // formattedStr contains a line separator (\r\n on Windows or \n on Linux) at the end of the log message
            pos = formattedString.IndexOf("\r\n", StringComparison.Ordinal);
            if (pos == -1) pos = formattedString.IndexOf("\n", StringComparison.Ordinal);

            if (pos != -1)
            {
                formattedString = formattedString.Substring(0, pos);
            }

            // Log the information
            Console.WriteLine(new string('-', 90));
            Console.WriteLine($"| Payload = '{payload_str}'");
            Console.WriteLine($"| Formatted string = '{formattedString}'");
            Console.WriteLine($"| Logger name = '{logger_name}'");
            Console.WriteLine($"| nlc_log_level = '{LogLevelConverter.toString((LogLevel)log_level)}'");
            Console.WriteLine($"| Local Time = '{TimeSinceEpochToLocaltimeString(time_since_epoch)}'");
            Console.WriteLine($"| Thread id = '{thread_id}'");
            Console.WriteLine(new string('-', 90));
        }

        /// <summary>
        /// Helper method for converting time since epoch to local time.
        /// </summary>
        /// <param name="timeSinceEpochInMs">Time since epoch in milliseconds.</param>
        /// <returns>Returns the converted local time as string.</returns>
        private string TimeSinceEpochToLocaltimeString(ulong timeSinceEpochInMs)
        {
            DateTime dateTime = DateTimeOffset.FromUnixTimeMilliseconds((long)timeSinceEpochInMs).DateTime.ToLocalTime();
            return dateTime.ToString("dd-MM-yyyy HH:mm:ss") + $":{timeSinceEpochInMs % 1000}";
        }

        /// <summary>
        /// Protected implementation of Dispose pattern
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    // unset the callback
                    _accessor.unsetLoggingCallback();
                }

                _disposed = true;
            }

            base.Dispose(disposing);
        }
    }
}
