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

namespace UtilsUI
{
    public class ControlHelper
    {
        /// <summary>
        /// Makes control visible on screen.
        /// </summary>
        public static readonly RoutedEvent BringToScreenEvent = EventManager.RegisterRoutedEvent("BringToScreen", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(ControlHelper));

        static ControlHelper()
        {
            EventManager.RegisterClassHandler(typeof(UIElement), ControlHelper.BringToScreenEvent, new RoutedEventHandler(OnBringToScreen));
            EventManager.RegisterClassHandler(typeof(FrameworkContentElement), ControlHelper.BringToScreenEvent, new RoutedEventHandler(OnBringToScreen));
        }

        public static void AddBringToScreenHandler(DependencyObject d, RoutedEventHandler handler)
        {
            var uie = d as UIElement;
            if (uie != null)
            {
                uie.AddHandler(BringToScreenEvent, handler);
            }
        }

        public static void RemoveBringToScreenHandler(DependencyObject d, RoutedEventHandler handler)
        {
            var uie = d as UIElement;
            if (uie != null)
            {
                uie.RemoveHandler(BringToScreenEvent, handler);
            }
        }

        private static void OnBringToScreen(object sender, RoutedEventArgs ev)
        {
            var isDestination = sender == ev.OriginalSource;

            var ui = sender as UIElement;
            if (ui != null)
            {
                ui.SetCurrentValue(UIElement.VisibilityProperty, Visibility.Visible);
            }

            var fe = sender as FrameworkElement;
            if (fe != null)
            {
                fe.BringIntoView();
            }

            var fce = sender as FrameworkContentElement;
            if (fce != null)
            {
                fce.BringIntoView();
            }

            var tabControl = sender as TabControl;
            if (tabControl != null)
            {
                // TODO select TabItem (only possible when not using ItemsSource)
            }

            var expander = sender as Expander;
            if (expander != null)
            {
                // XXX assumes target is inside content
                expander.SetCurrentValue(Expander.IsExpandedProperty, true);
            }

            var input = sender as IInputElement;
            if (input != null)
            {
                if (isDestination)
                    input.Focus();
            }
        }
    }

    public static class ControlExtensions
    {
        public static void BringToScreen(this UIElement element)
        {
            element.RaiseEvent(new RoutedEventArgs(ControlHelper.BringToScreenEvent));
        }
    }
}