using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ComponentModel;
using System.Reflection;
using PostSharp.Aspects;

namespace EQNetwork.Aspects
{
    [Serializable]
    public class NotifyPropertyChangedAttribute : LocationInterceptionAspect
    {
        public NotifyPropertyChangedAttribute()
        {
            AspectPriority = 400;
        }

        public override void OnSetValue(LocationInterceptionArgs args)
        {
            object oldValue = args.GetCurrentValue();
            object newValue = args.Value;
            base.OnSetValue(args);
            if (args.Instance is INotifyPropertyChanged)
            {
                if (!Equals(oldValue, newValue))
                    RaisePropertyChanged(args.Instance, args.LocationName);
            }
        }


        private void RaisePropertyChanged(object instance, string propertyName)
        {
            PropertyChangedEventHandler handler = GetPropertyChangedHandler(instance);
            if (handler != null)
                handler(instance, new PropertyChangedEventArgs(propertyName));
        }

        private PropertyChangedEventHandler GetPropertyChangedHandler(object instance)
        {
            Type type = instance.GetType().GetEvent("PropertyChanged").DeclaringType;
            FieldInfo propertyChanged = type.GetField("PropertyChanged",
                                                      BindingFlags.Instance | BindingFlags.NonPublic);
            if (propertyChanged != null)
                return propertyChanged.GetValue(instance) as PropertyChangedEventHandler;

            return null;
        }
    }
}
