using System;
using System.Windows;

namespace HandyControl.Interactivity
{
    public static class Interaction
    {
        private static readonly DependencyProperty TriggersProperty =
            DependencyProperty.RegisterAttached("ShadowTriggers", typeof(TriggerCollection), typeof(Interaction),
                new FrameworkPropertyMetadata(OnTriggersChanged));

        private static readonly DependencyProperty BehaviorsProperty =
            DependencyProperty.RegisterAttached("ShadowBehaviors", typeof(BehaviorCollection), typeof(Interaction),
                new FrameworkPropertyMetadata(OnBehaviorsChanged));

        internal static bool ShouldRunInDesignMode { get; set; }

        public static TriggerCollection GetTriggers(DependencyObject obj)
        {
            var triggerCollection = (TriggerCollection) obj.GetValue(TriggersProperty);
            if (triggerCollection == null)
            {
                triggerCollection = new TriggerCollection();
                obj.SetValue(TriggersProperty, triggerCollection);
            }
            return triggerCollection;
        }

        public static BehaviorCollection GetBehaviors(DependencyObject obj)
        {
            var behaviorCollection = (BehaviorCollection) obj.GetValue(BehaviorsProperty);
            if (behaviorCollection == null)
            {
                behaviorCollection = new BehaviorCollection();
                obj.SetValue(BehaviorsProperty, behaviorCollection);
            }
            return behaviorCollection;
        }

        private static void OnBehaviorsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            var oldValue = (BehaviorCollection) args.OldValue;
            var newValue = (BehaviorCollection) args.NewValue;
            if (Equals(oldValue, newValue))
                return;
            if (oldValue?.AssociatedObject != null)
                oldValue.Detach();
            if (newValue == null || obj == null)
                return;
            if (newValue.AssociatedObject != null)
                throw new InvalidOperationException(ExceptionStringTable
                    .CannotHostBehaviorCollectionMultipleTimesExceptionMessage);
            newValue.Attach(obj);
        }

        private static void OnTriggersChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            var oldValue = args.OldValue as TriggerCollection;
            var newValue = args.NewValue as TriggerCollection;
            if (Equals(oldValue, newValue))
                return;
            if (oldValue?.AssociatedObject != null)
                oldValue.Detach();
            if (newValue == null || obj == null)
                return;
            if (newValue.AssociatedObject != null)
                throw new InvalidOperationException(ExceptionStringTable
                    .CannotHostTriggerCollectionMultipleTimesExceptionMessage);
            newValue.Attach(obj);
        }

        internal static bool IsElementLoaded(FrameworkElement element)
        {
            return element.IsLoaded;
        }
    }
}
