using System.Text;

namespace Quadarax.Foundation.Core.Business.Processor.Task;

public class AffinityToken : IAffinityToken
{         
	#region *** Constants ***
    // ReSharper disable once InconsistentNaming
    public const char CCH_AT_SEP = '#';
	#endregion
	#region *** Public properties ***
	public string QueueIdentifier {get; private set;}
	public int? WorkerOrdinal {get; private set;}
	#endregion
	
	#region *** Constructor ***
	public AffinityToken()
	{
        QueueIdentifier = string.Empty;
	}
	public AffinityToken(string queueIdentifier, int workerOrdinal) : this()
	{
		Set(queueIdentifier, workerOrdinal);
	}
	public AffinityToken(string affinityTokenComplex) : this()
	{
		FromComplex(affinityTokenComplex);	
	}
    public AffinityToken(AffinityToken affinityToken)
    {
        if (affinityToken == null) throw new ArgumentNullException(nameof(affinityToken));

        QueueIdentifier = affinityToken.QueueIdentifier;
        WorkerOrdinal = affinityToken.WorkerOrdinal;
    }
	#endregion
	
	#region *** Public Operations ***
	public void FromComplex(string affinityTokenComplex)
	{
		if (string.IsNullOrEmpty(affinityTokenComplex)) throw new ArgumentNullException(nameof(affinityTokenComplex));;
		var parts = affinityTokenComplex.Split(CCH_AT_SEP, StringSplitOptions.RemoveEmptyEntries);
		if (parts.Length!=2) throw new ArgumentOutOfRangeException(nameof(affinityTokenComplex),$"Invalid format of affinity complex token value '{affinityTokenComplex}'.");
		
		QueueIdentifier = parts[0];
		WorkerOrdinal = int.Parse(parts[1]);
		
	}
	public void Set(string? queueIdentifier, int workerOrdinal)
	{
		if (string.IsNullOrEmpty(queueIdentifier)) throw new ArgumentNullException(nameof(queueIdentifier));
		QueueIdentifier = queueIdentifier;
		WorkerOrdinal = workerOrdinal;
	}
	
	public override string ToString()
	{
		var sb = new StringBuilder();
		if (!(string.IsNullOrEmpty(QueueIdentifier) || WorkerOrdinal == null))
		{
			sb.Append(QueueIdentifier).Append(CCH_AT_SEP).Append(WorkerOrdinal.Value);
		}
		return sb.ToString();
	}
	
	public bool Equals (AffinityToken? other)
	{
		if (other == null) return false;
		return string.Equals(ToString(), other.ToString());
	}
	#endregion
}
