using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.BL.ValueObjects;
using Tango.Core;
using Tango.Core.ExtensionMethods;
namespace Tango.BL.ActionLogs
{
///
/// Represents the default implementation.
///
///
///
public class DefaultActionLogManager : ExtendedObject, IActionLogManager
{
///
/// Gets or sets the action log comparer used to compare related objects.
///
public IActionLogComparer ActionLogComparer { get; set; }
///
/// Gets or sets a value indicating whether to perform the logging operations asynchronously.
///
public bool IsAsync { get; set; }
///
/// Initializes a new instance of the class.
///
public DefaultActionLogManager()
{
IsAsync = true;
ActionLogComparer = new DefaultActionLogComparer();
}
///
/// Inserts a new action log (main entry point).
///
/// The type.
/// The user unique identifier.
/// Name of the related object.
/// The related object unique identifier.
/// The diffference node tree.
/// The message.
public void InsertLog(ActionLogType type, string userGuid, string relatedObjectName, string relatedObjectGuid, ActionLogDifference difference, string message = null)
{
Task task = new Task(() =>
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
try
{
ActionLog log = new ActionLog();
log.ActionType = type;
log.LastUpdated = DateTime.UtcNow;
log.UserGuid = userGuid;
log.RelatedObjectName = relatedObjectName;
log.RelatedObjectGuid = relatedObjectGuid;
log.Message = message;
log.DifferenceObject = difference;
db.ActionLogs.Add(log);
db.SaveChanges();
LogManager.Log($"Action log '{type}' inserted.");
if (difference != null && difference.Children.Count > 0)
{
Debug.WriteLine($"Action log differences:\n{difference.ToJsonString()}");
}
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error inserting action log '{type}'.");
}
}
});
if (IsAsync)
{
task.Start();
}
else
{
task.RunSynchronously();
}
}
///
/// Inserts a new action log (comparison entry).
///
/// The type.
/// The user unique identifier.
/// Name of the related object.
/// The related object before the change.
/// The related object after the change.
/// The message.
public void InsertLog(ActionLogType type, string userGuid, string relatedObjectName, IActionLogComparable relatedObjectBefore, IActionLogComparable relatedObjectAfter, string message = null)
{
Task task = new Task(() =>
{
ActionLogDifference diff = new ActionLogDifference();
bool insertWhenNoDifference = false;
if (ActionLogComparer != null)
{
try
{
diff = ActionLogComparer.Compare(relatedObjectBefore, relatedObjectAfter).Result;
}
catch (Exception ex)
{
insertWhenNoDifference = true;
LogManager.Log(ex, $"Error while comparing for action log '{type}'.");
}
if (diff.Children.Count > 0 || insertWhenNoDifference)
{
InsertLog(type, userGuid, relatedObjectName, GetRelatedObjectGuid(relatedObjectBefore, relatedObjectAfter), diff, message);
}
else
{
LogManager.Log($"Action log '{type}' was about to be inserted but skipped due to no differences.");
}
}
else
{
Debug.WriteLine("No comparer defined for action log.");
InsertLog(type, userGuid, relatedObjectName, GetRelatedObjectGuid(relatedObjectBefore, relatedObjectAfter), diff, message);
}
});
if (IsAsync)
{
task.Start();
}
else
{
task.RunSynchronously();
}
}
///
/// Inserts a new action log (comparison entry).
///
/// The type.
/// The user.
/// Name of the related object.
/// The related object before the change.
/// The related object after the change.
/// The message.
public void InsertLog(ActionLogType type, User user, string relatedObjectName, IActionLogComparable relatedObjectBefore, IActionLogComparable relatedObjectAfter, string message = null)
{
InsertLog(type, user.Guid, relatedObjectName, relatedObjectBefore, relatedObjectAfter, message);
}
///
/// Inserts a new action log (deletion/creation entry).
///
/// The type.
/// The user.
/// Name of the related object.
/// The related object.
/// The message.
/// if set to true will create a one way difference tree (use when the related object was deleted and needs to be monitored).
public void InsertLog(ActionLogType type, User user, string relatedObjectName, IActionLogComparable relatedObject, string message = null, bool serializeRelatedObject = false)
{
if (serializeRelatedObject)
{
InsertLog(type, user.Guid, relatedObjectName, relatedObject, null, message);
}
else
{
InsertLog(type, user.Guid, relatedObjectName, relatedObject?.Guid, message);
}
}
///
/// Inserts a new action log (creation entry).
///
/// The type.
/// The user unique identifier.
/// Name of the related object.
/// The related object unique identifier.
/// The message.
public void InsertLog(ActionLogType type, string userGuid, string relatedObjectName, string relatedObjectGuid, string message = null)
{
InsertLog(type, userGuid, relatedObjectName, relatedObjectGuid, null, message);
}
///
/// Inserts a new action log (nutral entry).
///
/// The type.
/// The user unique identifier.
/// The message.
public void InsertLog(ActionLogType type, string userGuid, string message = null)
{
InsertLog(type, userGuid, null, null, message);
}
///
/// Inserts a new action log (nutral entry).
///
/// The type.
/// The user.
/// The message.
public void InsertLog(ActionLogType type, User user, string message = null)
{
InsertLog(type, user.Guid, message);
}
///
/// Gets the related object unique identifier.
///
/// The before.
/// The after.
///
private String GetRelatedObjectGuid(IActionLogComparable before, IActionLogComparable after)
{
if (before != null)
{
return before.Guid;
}
if (after != null)
{
return after.Guid;
}
return null;
}
}
}