#if XFORMS
namespace Caliburn.Micro.Core.Xamarin.Forms
#else
namespace Caliburn.Micro
#endif 
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
#if WinRT81
    using Windows.UI.Xaml;
    using Microsoft.Xaml.Interactivity;
    using TriggerBase = Microsoft.Xaml.Interactivity.IBehavior;
#elif XFORMS
    using global::Xamarin.Forms;
    using UIElement = global::Xamarin.Forms.Element;
    using FrameworkElement = global::Xamarin.Forms.VisualElement;
    using DependencyProperty = global::Xamarin.Forms.BindableProperty;
    using DependencyObject = global::Xamarin.Forms.BindableObject;
#else
    using System.Windows;
    using System.Windows.Interactivity;
    using TriggerBase = System.Windows.Interactivity.TriggerBase;
    using Caliburn.Micro.Core;
#endif
    /// 
    ///   Host's attached properties related to routed UI messaging.
    /// 
    public static class Message {
        internal static readonly DependencyProperty HandlerProperty =
            DependencyPropertyHelper.RegisterAttached(
                "Handler",
                typeof(object),
                typeof(Message),
                null
                );
        static readonly DependencyProperty MessageTriggersProperty =
            DependencyPropertyHelper.RegisterAttached(
                "MessageTriggers",
                typeof(TriggerBase[]),
                typeof(Message),
                null
                );
        /// 
        ///   Places a message handler on this element.
        /// 
        ///  The element. 
        ///  The message handler. 
        public static void SetHandler(DependencyObject d, object value) {
            d.SetValue(HandlerProperty, value);
        }
        /// 
        ///   Gets the message handler for this element.
        /// 
        ///  The element. 
        ///  The message handler. 
        public static object GetHandler(DependencyObject d) {
            return d.GetValue(HandlerProperty);
        }
        /// 
        ///   A property definition representing attached triggers and messages.
        /// 
        public static readonly DependencyProperty AttachProperty =
            DependencyPropertyHelper.RegisterAttached(
                "Attach",
                typeof(string),
                typeof(Message),
                null, 
                OnAttachChanged
                );
        /// 
        ///   Sets the attached triggers and messages.
        /// 
        ///  The element to attach to. 
        ///  The parsable attachment text. 
        public static void SetAttach(DependencyObject d, string attachText) {
            d.SetValue(AttachProperty, attachText);
        }
        /// 
        ///   Gets the attached triggers and messages.
        /// 
        ///  The element that was attached to. 
        ///  The parsable attachment text. 
        public static string GetAttach(DependencyObject d) {
            return d.GetValue(AttachProperty) as string;
        }
        static void OnAttachChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            if (e.NewValue == e.OldValue) {
                return;
            }
            var messageTriggers = (TriggerBase[])d.GetValue(MessageTriggersProperty);
#if WinRT81
            var allTriggers = Interaction.GetBehaviors(d);
            if (messageTriggers != null)
            {
                messageTriggers.OfType().Apply(x => allTriggers.Remove(x));
            }
            var newTriggers = Parser.Parse(d, e.NewValue as string).ToArray();
            newTriggers.OfType().Apply(allTriggers.Add);
#elif XFORMS
            var visualElement = d as VisualElement;
            var allTriggers = visualElement != null ? visualElement.Triggers : new List();
            if (messageTriggers != null) {
                messageTriggers.Apply(x => allTriggers.Remove(x));
            }
            var newTriggers = Parser.Parse(d, e.NewValue as string).ToArray();
            newTriggers.Apply(allTriggers.Add);
#else
            var allTriggers = Interaction.GetTriggers(d);
             if (messageTriggers != null) {
                messageTriggers.Apply(x => allTriggers.Remove(x));
            }
            var newTriggers = Parser.Parse(d, e.NewValue as string).ToArray();
            newTriggers.Apply(allTriggers.Add);
#endif
            if (newTriggers.Length > 0) {
                d.SetValue(MessageTriggersProperty, newTriggers);
            }
            else {
                d.ClearValue(MessageTriggersProperty);
            }
        }
    }
}