﻿using PostSharp.Aspects;
using PostSharp.Aspects.Dependencies;
using PostSharp.Reflection;
using System;

namespace TransitApi.Domain.Models.ValidationAttributes
{
    /// <summary>
    /// Validates the parameter of type string to be exactly a certain length. Throws a
    /// System.ArgumentException if assigned a value of length outside this range.
    /// </summary>
    [Serializable]
    public sealed class StringLengthExactlyAttribute : LocationInterceptionAspect, ILocationValidationAspect<string>
    {
        public StringLengthExactlyAttribute(int length)
        {
            this.Length = length;

            this.ErrorMessage = "The parameter '{0}' must be a string of length " + Length + ".";
        }

        public string ErrorMessage { get; private set; }

        public int Length { get; private set; }

        public override void OnSetValue(LocationInterceptionArgs args)
        {
            Exception ex = ValidateValue((string)args.Value, args.LocationName, args.Location.LocationKind);

            if (ex != null)
            {
                throw ex;
            }

            args.ProceedSetValue();
        }

        public Exception ValidateValue(string value, string locationName, LocationKind locationKind)
        {
            if (string.IsNullOrEmpty(value))
            {
                return null;
            }

            return value.Length != Length ? new ArgumentException(locationName, string.Format(ErrorMessage, locationName)) : null;
        }
    }
}