using F4SD_AdaptableIcon.Enums;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using static C4IT.Logging.cLogManager;

namespace FasdDesktopUi.Basics.UserControls.AdaptableIcon
{
    public partial class AdaptableIcon : UserControl, ICommandSource
    {
        private readonly cIconPainter.cIconInformation iconInformation = new cIconPainter.cIconInformation();

        #region Properties  

        #region Command Properties

        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(AdaptableIcon), new PropertyMetadata(null));


        public object CommandParameter
        {
            get { return (object)GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(AdaptableIcon), new PropertyMetadata(null));


        public IInputElement CommandTarget
        {
            get { return (IInputElement)GetValue(CommandTargetProperty); }
            set { SetValue(CommandTargetProperty, value); }
        }

        public static readonly DependencyProperty CommandTargetProperty =
            DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(AdaptableIcon), new PropertyMetadata(null));


        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonUp(e);

            try
            {
                if (Command is null)
                    return;

                if (!Command.CanExecute(CommandParameter))
                    return;

                if (Command is RoutedCommand routedCommand)
                    routedCommand.Execute(CommandParameter, CommandTarget);
                else
                    Command.Execute(CommandParameter);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        protected override void OnTouchDown(TouchEventArgs e)
        {
            base.OnTouchDown(e);

            try
            {
                if (Command is null)
                    return;

                if (!Command.CanExecute(CommandParameter))
                    return;

                if (Command is RoutedCommand routedCommand)
                    routedCommand.Execute(CommandParameter, CommandTarget);
                else
                    Command.Execute(CommandParameter);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        #endregion

        public string IconName { get => iconInformation?.IconName; }

        #region IconBackgroundColor DP

        public static readonly DependencyProperty IconBackgroundColorProperty =
            DependencyProperty.Register("IconBackgroundColor", typeof(Brush), typeof(AdaptableIcon), new PropertyMetadata(Brushes.Transparent, new PropertyChangedCallback(IconInformationChanged)));

        public Brush IconBackgroundColor
        {
            get { return (Brush)GetValue(IconBackgroundColorProperty); }
            set { SetValue(IconBackgroundColorProperty, value); }
        }

        #endregion

        #region IconHeight DP

        public static readonly DependencyProperty IconHeightProperty =
            DependencyProperty.Register("IconHeight", typeof(double), typeof(AdaptableIcon), new PropertyMetadata(30.0, new PropertyChangedCallback(IconInformationChanged)));
        public double IconHeight
        {
            get { return (double)GetValue(IconHeightProperty); }
            set { SetValue(IconHeightProperty, value); }
        }

        #endregion

        #region IconWidth DP

        public static readonly DependencyProperty IconWidthProperty =
            DependencyProperty.Register("IconWidth", typeof(double), typeof(AdaptableIcon), new PropertyMetadata(30.0, new PropertyChangedCallback(IconInformationChanged)));
        public double IconWidth
        {
            get { return (double)GetValue(IconWidthProperty); }
            set { SetValue(IconWidthProperty, value); }
        }

        #endregion

        #region BorderPadding DP

        public static readonly DependencyProperty BorderPaddingProperty =
            DependencyProperty.Register("BorderPadding", typeof(Thickness), typeof(AdaptableIcon), new PropertyMetadata(new Thickness(7.5), new PropertyChangedCallback(IconInformationChanged)));
        public Thickness BorderPadding
        {
            get { return (Thickness)GetValue(BorderPaddingProperty); }
            set { SetValue(BorderPaddingProperty, value); }
        }

        #endregion

        #region IconCornerRadius DP

        public static readonly DependencyProperty IconCornerRadiusProperty =
            DependencyProperty.Register("IconCornerRadius", typeof(CornerRadius), typeof(AdaptableIcon), new PropertyMetadata(new CornerRadius(5), new PropertyChangedCallback(IconInformationChanged)));
        public CornerRadius IconCornerRadius
        {
            get { return (CornerRadius)GetValue(IconCornerRadiusProperty); }
            set { SetValue(IconCornerRadiusProperty, value); }
        }

        #endregion

        #region PrimaryIconColor DP

        public static readonly DependencyProperty PrimaryIconColorProperty =
            DependencyProperty.Register("PrimaryIconColor", typeof(SolidColorBrush), typeof(AdaptableIcon), new PropertyMetadata(Brushes.Black, new PropertyChangedCallback(IconInformationChanged)));
        public SolidColorBrush PrimaryIconColor
        {
            get { return (SolidColorBrush)GetValue(PrimaryIconColorProperty); }
            set { SetValue(PrimaryIconColorProperty, value); }
        }

        #endregion

        #region SecondaryIconColor DP

        public static readonly DependencyProperty SecondaryIconColorProperty =
            DependencyProperty.Register("SecondaryIconColor", typeof(Brush), typeof(AdaptableIcon), new PropertyMetadata(Brushes.White, new PropertyChangedCallback(IconInformationChanged)));
        public Brush SecondaryIconColor
        {
            get { return (Brush)GetValue(SecondaryIconColorProperty); }
            set { SetValue(SecondaryIconColorProperty, value); }
        }

        #endregion

        #region SelectedInternIcon

        public enumInternIcons? SelectedInternIcon
        {
            get { return (enumInternIcons?)GetValue(SelectedInternIconProperty); }
            set { SetValue(SelectedInternIconProperty, value); }
        }

        public static readonly DependencyProperty SelectedInternIconProperty =
            DependencyProperty.Register("SelectedInternIcon", typeof(enumInternIcons?), typeof(AdaptableIcon), new PropertyMetadata(null, new PropertyChangedCallback(SelectedIconChanged)), ValidateInternIcon);

        private static bool ValidateInternIcon(object o)
        {
            return true;
        }

        #endregion

        #region SelectedInternGif

        public static readonly DependencyProperty SelectedInternGifProperty =
            DependencyProperty.Register("SelectedInternGif", typeof(enumInternGif?), typeof(AdaptableIcon), new PropertyMetadata(null, new PropertyChangedCallback(SelectedIconChanged)));

        public enumInternGif? SelectedInternGif
        {
            get { return (enumInternGif?)GetValue(SelectedInternGifProperty); }
            set { SetValue(SelectedInternGifProperty, value); }
        }

        #endregion

        #region SelectedMaterialIcon

        public MaterialIcons.MaterialIconType? SelectedMaterialIcon
        {
            get { return (MaterialIcons.MaterialIconType?)GetValue(SelectedMaterialIconProperty); }
            set { SetValue(SelectedMaterialIconProperty, value); }
        }

        public static readonly DependencyProperty SelectedMaterialIconProperty =
            DependencyProperty.Register("SelectedMaterialIcon", typeof(MaterialIcons.MaterialIconType?), typeof(AdaptableIcon), new PropertyMetadata(null, new PropertyChangedCallback(SelectedIconChanged)));

        #endregion

        #region SelectedCountryCode

        public enumCountryCode? SelectedCountryCode
        {
            get { return (enumCountryCode?)GetValue(SelectedCountryCodeProperty); }
            set { SetValue(SelectedCountryCodeProperty, value); }
        }

        public static readonly DependencyProperty SelectedCountryCodeProperty =
            DependencyProperty.Register("SelectedCountryCode", typeof(enumCountryCode?), typeof(AdaptableIcon), new PropertyMetadata(null, new PropertyChangedCallback(SelectedIconChanged)));

        #endregion


        private static void IconInformationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                if (d is AdaptableIcon _me)
                    _me.UpdateIconInformation();
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private static void SelectedIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(d))
                    return;

                if (!(d is AdaptableIcon _me))
                    return;

                if (e.NewValue is null)
                    return;

                if (e.NewValue is enumInternIcons selectedInternIcon)
                    _me.iconInformation.UpdateIconInformation(selectedInternIcon);

                if (e.NewValue is enumInternGif selectedInternGif)
                    _me.iconInformation.UpdateIconInformation(selectedInternGif);

                if (e.NewValue is MaterialIcons.MaterialIconType selectedMaterialIcon)
                    _me.iconInformation.UpdateIconInformation(selectedMaterialIcon);

                if (e.NewValue is enumCountryCode selectedCountryCode)
                    _me.iconInformation.UpdateIconInformation(selectedCountryCode);

                _me.UpdateIconInformation();
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }


        #endregion

        public AdaptableIcon()
        {
            InitializeComponent();
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            UpdateIconInformation();
        }

        public (enumInternIcons?, enumInternGif?, MaterialIcons.MaterialIconType?, enumCountryCode?) GetCurrentIcon()
        {
            return (SelectedInternIcon, SelectedInternGif, SelectedMaterialIcon, SelectedCountryCode);
        }

        public void SetIcon((enumInternIcons? InternIcon, enumInternGif? InternGif, MaterialIcons.MaterialIconType? MaterialIcon, enumCountryCode? CountryCode) IconValues)
        {
            try
            {
                SelectedInternIcon = IconValues.InternIcon;
                SelectedInternGif = IconValues.InternGif;
                SelectedMaterialIcon = IconValues.MaterialIcon;
                SelectedCountryCode = IconValues.CountryCode;
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void UpdateIconInformation()
        {
            try
            {
                iconInformation.IconHeightInPx = IconHeight;
                iconInformation.IconWidthInPx = IconWidth;
                iconInformation.PrimaryIconColor = PrimaryIconColor;
                iconInformation.SecondaryIconColor = SecondaryIconColor;

                UpdateIcon();
                UpdateIconBorder();
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void UpdateIcon()
        {
            try
            {
                MainGrid.Children.Clear();

                var newIcon = cIconPainter.GetIcon(iconInformation);

                if (newIcon != null)
                    MainGrid.Children.Add(newIcon);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void UpdateIconBorder()
        {
            try
            {
                IconBorder.Background = IconBackgroundColor;
                IconBorder.Height = IconHeight;
                IconBorder.Width = IconWidth;
                IconBorder.CornerRadius = IconCornerRadius;
                IconBorder.Padding = BorderPadding;
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }
    }
}
