using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using Standard;

namespace Microsoft.Windows.Shell
{
    public sealed class TaskbarItemInfo : Freezable
    {
        protected override Freezable CreateInstanceCore()
        {
            return new TaskbarItemInfo();
        }

        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
        public static TaskbarItemInfo GetTaskbarItemInfo(Window window)
        {
            Verify.IsNotNull<Window>(window, "window");
            return (TaskbarItemInfo) window.GetValue(TaskbarItemInfo.TaskbarItemInfoProperty);
        }

        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
        public static void SetTaskbarItemInfo(Window window, TaskbarItemInfo value)
        {
            Verify.IsNotNull<Window>(window, "window");
            window.SetValue(TaskbarItemInfo.TaskbarItemInfoProperty, value);
        }

        private static void _OnTaskbarItemInfoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (DesignerProperties.GetIsInDesignMode(d))
            {
                return;
            }
            Window window = (Window) d;
            TaskbarItemInfo taskbarItemInfo = (TaskbarItemInfo) e.OldValue;
            TaskbarItemInfo taskbarItemInfo2 = (TaskbarItemInfo) e.NewValue;
            if (taskbarItemInfo == taskbarItemInfo2)
            {
                return;
            }
            if (!Utility.IsOSWindows7OrNewer)
            {
                return;
            }
            if (taskbarItemInfo != null && taskbarItemInfo._window != null)
            {
                taskbarItemInfo._DetachWindow();
            }
            if (taskbarItemInfo2 != null)
            {
                taskbarItemInfo2._SetWindow(window);
            }
        }

        private static object _CoerceTaskbarItemInfoValue(DependencyObject d, object value)
        {
            if (DesignerProperties.GetIsInDesignMode(d))
            {
                return value;
            }
            Verify.IsNotNull<DependencyObject>(d, "d");
            Window window = (Window) d;
            TaskbarItemInfo taskbarItemInfo = (TaskbarItemInfo) value;
            if (taskbarItemInfo != null && taskbarItemInfo._window != null && taskbarItemInfo._window != window)
            {
                throw new NotSupportedException();
            }
            window.VerifyAccess();
            return taskbarItemInfo;
        }

        public TaskbarItemProgressState ProgressState
        {
            get
            {
                return (TaskbarItemProgressState) base.GetValue(TaskbarItemInfo.ProgressStateProperty);
            }
            set
            {
                base.SetValue(TaskbarItemInfo.ProgressStateProperty, value);
            }
        }

        private void _OnProgressStateChanged()
        {
            if (!this._isAttached)
            {
                return;
            }
            this._UpdateProgressState(true);
        }

        private static TaskbarItemProgressState _CoerceProgressState(TaskbarItemProgressState value)
        {
            switch (value)
            {
                case TaskbarItemProgressState.None:
                case TaskbarItemProgressState.Indeterminate:
                case TaskbarItemProgressState.Normal:
                case TaskbarItemProgressState.Error:
                case TaskbarItemProgressState.Paused:
                    break;
                default:
                    value = TaskbarItemProgressState.None;
                    break;
            }
            return value;
        }

        public double ProgressValue
        {
            get
            {
                return (double) base.GetValue(TaskbarItemInfo.ProgressValueProperty);
            }
            set
            {
                base.SetValue(TaskbarItemInfo.ProgressValueProperty, value);
            }
        }

        private void _OnProgressValueChanged()
        {
            if (!this._isAttached)
            {
                return;
            }
            this._UpdateProgressValue(true);
        }

        private static double _CoerceProgressValue(double progressValue)
        {
            if (double.IsNaN(progressValue))
            {
                progressValue = 0.0;
            }
            progressValue = Math.Max(progressValue, 0.0);
            progressValue = Math.Min(1.0, progressValue);
            return progressValue;
        }

        public ImageSource Overlay
        {
            get
            {
                return (ImageSource) base.GetValue(TaskbarItemInfo.OverlayProperty);
            }
            set
            {
                base.SetValue(TaskbarItemInfo.OverlayProperty, value);
            }
        }

        private void _OnOverlayChanged()
        {
            if (!this._isAttached)
            {
                return;
            }
            this._UpdateOverlay(true);
        }

        public string Description
        {
            get
            {
                return (string) base.GetValue(TaskbarItemInfo.DescriptionProperty);
            }
            set
            {
                base.SetValue(TaskbarItemInfo.DescriptionProperty, value);
            }
        }

        private void _OnDescriptionChanged()
        {
            if (!this._isAttached)
            {
                return;
            }
            this._UpdateTooltip(true);
        }

        public Thickness ThumbnailClipMargin
        {
            get
            {
                return (Thickness) base.GetValue(TaskbarItemInfo.ThumbnailClipMarginProperty);
            }
            set
            {
                base.SetValue(TaskbarItemInfo.ThumbnailClipMarginProperty, value);
            }
        }

        private void _OnThumbnailClipMarginChanged()
        {
            if (!this._isAttached)
            {
                return;
            }
            this._UpdateThumbnailClipping(true);
        }

        private static Thickness _CoerceThumbnailClipMargin(Thickness margin)
        {
            if (margin.Left < 0.0 || margin.Right < 0.0 || margin.Top < 0.0 || margin.Bottom < 0.0)
            {
                return TaskbarItemInfo._EmptyThickness;
            }
            return margin;
        }

        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Infos")]
        public ThumbButtonInfoCollection ThumbButtonInfos
        {
            get
            {
                return (ThumbButtonInfoCollection) base.GetValue(TaskbarItemInfo.ThumbButtonInfosProperty);
            }
            set
            {
                base.SetValue(TaskbarItemInfo.ThumbButtonInfosProperty, value);
            }
        }

        private void _OnThumbButtonsChanged()
        {
            if (!this._isAttached)
            {
                return;
            }
            this._UpdateThumbButtons(true);
        }

        private IntPtr _GetHICONFromImageSource(ImageSource image, Size dimensions)
        {
            if (this._gdipToken == null)
            {
                this._gdipToken = SafeGdiplusStartupToken.Startup();
            }
            return Utility.GenerateHICON(image, dimensions);
        }

        public TaskbarItemInfo()
        {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                ITaskbarList taskbarList = null;
                try
                {
                    taskbarList = CLSID.CoCreateInstance<ITaskbarList>("56FDF344-FD6D-11d0-958A-006097C9A090");
                    taskbarList.HrInit();
                    this._taskbarList = (taskbarList as ITaskbarList3);
                    taskbarList = null;
                }
                finally
                {
                    Utility.SafeRelease<ITaskbarList>(ref taskbarList);
                }
                this._overlaySize = new Size((double) NativeMethods.GetSystemMetrics(SM.CXSMICON), (double) NativeMethods.GetSystemMetrics(SM.CYSMICON));
            }
            this.ThumbButtonInfos = new ThumbButtonInfoCollection();
        }

        private void _SetWindow(Window window)
        {
            if (window == null)
            {
                return;
            }
            this._window = window;
            if (this._taskbarList == null)
            {
                return;
            }
            IntPtr handle = new WindowInteropHelper(this._window).Handle;
            if (!(handle != IntPtr.Zero))
            {
                this._window.SourceInitialized += this._OnWindowSourceInitialized;
                return;
            }
            this._hwndSource = HwndSource.FromHwnd(handle);
            this._hwndSource.AddHook(new HwndSourceHook(this._WndProc));
            this._OnIsAttachedChanged(true);
        }

        private void _OnWindowSourceInitialized(object sender, EventArgs e)
        {
            this._window.SourceInitialized -= this._OnWindowSourceInitialized;
            IntPtr handle = new WindowInteropHelper(this._window).Handle;
            this._hwndSource = HwndSource.FromHwnd(handle);
            this._hwndSource.AddHook(new HwndSourceHook(this._WndProc));
            MSGFLTINFO msgfltinfo;
            NativeMethods.ChangeWindowMessageFilterEx(handle, TaskbarItemInfo.WM_TASKBARBUTTONCREATED, MSGFLT.ALLOW, out msgfltinfo);
            NativeMethods.ChangeWindowMessageFilterEx(handle, WM.COMMAND, MSGFLT.ALLOW, out msgfltinfo);
        }

        private IntPtr _WndProc(IntPtr hwnd, int uMsg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (uMsg == (int) TaskbarItemInfo.WM_TASKBARBUTTONCREATED)
            {
                this._OnIsAttachedChanged(true);
                this._isAttached = true;
                handled = false;
            }
            else if (uMsg != 5)
            {
                if (uMsg == 273 && Utility.HIWORD(wParam.ToInt32()) == 6144)
                {
                    int index = Utility.LOWORD(wParam.ToInt32());
                    this.ThumbButtonInfos[index].InvokeClick();
                    handled = true;
                }
            }
            else
            {
                this._UpdateThumbnailClipping(this._isAttached);
                handled = false;
            }
            return IntPtr.Zero;
        }

        private void _OnIsAttachedChanged(bool attached)
        {
            this._haveAddedButtons = false;
            if (!attached && this._hwndSource == null)
            {
                return;
            }
            this._UpdateOverlay(attached);
            this._UpdateProgressState(attached);
            this._UpdateProgressValue(attached);
            this._UpdateTooltip(attached);
            this._UpdateThumbnailClipping(attached);
            this._UpdateThumbButtons(attached);
            if (!attached)
            {
                this._hwndSource = null;
            }
        }

        private void _DetachWindow()
        {
            this._window.SourceInitialized -= this._OnWindowSourceInitialized;
            this._isAttached = false;
            this._OnIsAttachedChanged(false);
            this._window = null;
        }

        private HRESULT _UpdateOverlay(bool attached)
        {
            ImageSource overlay = this.Overlay;
            if (overlay == null || !attached)
            {
                return this._taskbarList.SetOverlayIcon(this._hwndSource.Handle, IntPtr.Zero, null);
            }
            IntPtr hIcon = IntPtr.Zero;
            HRESULT result;
            try
            {
                hIcon = this._GetHICONFromImageSource(overlay, this._overlaySize);
                result = this._taskbarList.SetOverlayIcon(this._hwndSource.Handle, hIcon, null);
            }
            finally
            {
                Utility.SafeDestroyIcon(ref hIcon);
            }
            return result;
        }

        private HRESULT _UpdateTooltip(bool attached)
        {
            string pszTip = this.Description ?? "";
            if (!attached)
            {
                pszTip = "";
            }
            return this._taskbarList.SetThumbnailTooltip(this._hwndSource.Handle, pszTip);
        }

        private HRESULT _UpdateProgressValue(bool attached)
        {
            if (!attached || this.ProgressState == TaskbarItemProgressState.None || this.ProgressState == TaskbarItemProgressState.Indeterminate)
            {
                return HRESULT.S_OK;
            }
            ulong ullCompleted = (ulong) (this.ProgressValue * 1000.0);
            return this._taskbarList.SetProgressValue(this._hwndSource.Handle, ullCompleted, 1000UL);
        }

        private HRESULT _UpdateProgressState(bool attached)
        {
            TaskbarItemProgressState progressState = this.ProgressState;
            TBPF tbpFlags = TBPF.NOPROGRESS;
            if (attached)
            {
                switch (progressState)
                {
                    case TaskbarItemProgressState.None:
                        tbpFlags = TBPF.NOPROGRESS;
                        break;
                    case TaskbarItemProgressState.Indeterminate:
                        tbpFlags = TBPF.INDETERMINATE;
                        break;
                    case TaskbarItemProgressState.Normal:
                        tbpFlags = TBPF.NORMAL;
                        break;
                    case TaskbarItemProgressState.Error:
                        tbpFlags = TBPF.ERROR;
                        break;
                    case TaskbarItemProgressState.Paused:
                        tbpFlags = TBPF.PAUSED;
                        break;
                    default:
                        tbpFlags = TBPF.NOPROGRESS;
                        break;
                }
            }
            HRESULT result = this._taskbarList.SetProgressState(this._hwndSource.Handle, tbpFlags);
            if (result.Succeeded)
            {
                result = this._UpdateProgressValue(attached);
            }
            return result;
        }

        private HRESULT _UpdateThumbnailClipping(bool attached)
        {
            RefRECT prcClip = null;
            if (attached && this.ThumbnailClipMargin != TaskbarItemInfo._EmptyThickness)
            {
                Thickness thumbnailClipMargin = this.ThumbnailClipMargin;
                RECT clientRect = NativeMethods.GetClientRect(this._hwndSource.Handle);
                Rect rect = DpiHelper.DeviceRectToLogical(new Rect((double) clientRect.Left, (double) clientRect.Top, (double) clientRect.Width, (double) clientRect.Height));
                if (thumbnailClipMargin.Left + thumbnailClipMargin.Right >= rect.Width || thumbnailClipMargin.Top + thumbnailClipMargin.Bottom >= rect.Height)
                {
                    prcClip = new RefRECT(0, 0, 0, 0);
                }
                else
                {
                    Rect logicalRectangle = new Rect(thumbnailClipMargin.Left, thumbnailClipMargin.Top, rect.Width - thumbnailClipMargin.Left - thumbnailClipMargin.Right, rect.Height - thumbnailClipMargin.Top - thumbnailClipMargin.Bottom);
                    Rect rect2 = DpiHelper.LogicalRectToDevice(logicalRectangle);
                    prcClip = new RefRECT((int) rect2.Left, (int) rect2.Top, (int) rect2.Right, (int) rect2.Bottom);
                }
            }
            return this._taskbarList.SetThumbnailClip(this._hwndSource.Handle, prcClip);
        }

        private HRESULT _RegisterThumbButtons()
        {
            HRESULT hresult = HRESULT.S_OK;
            if (!this._haveAddedButtons)
            {
                THUMBBUTTON[] array = new THUMBBUTTON[7];
                for (int i = 0; i < 7; i++)
                {
                    array[i] = new THUMBBUTTON
                    {
                        iId = (uint) i,
                        dwFlags = (THBF.DISABLED | THBF.NOBACKGROUND | THBF.HIDDEN),
                        dwMask = (THB.ICON | THB.TOOLTIP | THB.FLAGS)
                    };
                }
                hresult = this._taskbarList.ThumbBarAddButtons(this._hwndSource.Handle, (uint) array.Length, array);
                if (hresult == HRESULT.E_INVALIDARG)
                {
                    hresult = HRESULT.S_FALSE;
                }
                this._haveAddedButtons = hresult.Succeeded;
            }
            return hresult;
        }

        private HRESULT _UpdateThumbButtons(bool attached)
        {
            THUMBBUTTON[] array = new THUMBBUTTON[7];
            HRESULT result = this._RegisterThumbButtons();
            if (result.Failed)
            {
                return result;
            }
            ThumbButtonInfoCollection thumbButtonInfos = this.ThumbButtonInfos;
            HRESULT result2;
            try
            {
                uint num = 0u;
                if (!attached || thumbButtonInfos == null)
                {
                    goto IL_1AE;
                }
                using (FreezableCollection<ThumbButtonInfo>.Enumerator enumerator = thumbButtonInfos.GetEnumerator())
                {
                    while (enumerator.MoveNext())
                    {
                        ThumbButtonInfo thumbButtonInfo = enumerator.Current;
                        THUMBBUTTON thumbbutton = new THUMBBUTTON
                        {
                            iId = num,
                            dwMask = (THB.ICON | THB.TOOLTIP | THB.FLAGS)
                        };
                        switch (thumbButtonInfo.Visibility)
                        {
                            case Visibility.Visible:
                                goto IL_A5;
                            case Visibility.Hidden:
                                thumbbutton.dwFlags = (THBF.DISABLED | THBF.NOBACKGROUND);
                                thumbbutton.hIcon = IntPtr.Zero;
                                break;
                            case Visibility.Collapsed:
                                thumbbutton.dwFlags = THBF.HIDDEN;
                                break;
                            default:
                                goto IL_A5;
                        }
IL_146:
                        array[(int) ((UIntPtr) num)] = thumbbutton;
                        num += 1u;
                        if (num != 7u)
                        {
                            continue;
                        }
                        break;
IL_A5:
                        thumbbutton.szTip = (thumbButtonInfo.Description ?? "");
                        thumbbutton.hIcon = this._GetHICONFromImageSource(thumbButtonInfo.ImageSource, this._overlaySize);
                        if (!thumbButtonInfo.IsBackgroundVisible)
                        {
                            thumbbutton.dwFlags |= THBF.NOBACKGROUND;
                        }
                        if (!thumbButtonInfo.IsEnabled)
                        {
                            thumbbutton.dwFlags |= THBF.DISABLED;
                        }
                        else
                        {
                            thumbbutton.dwFlags = thumbbutton.dwFlags;
                        }
                        if (!thumbButtonInfo.IsInteractive)
                        {
                            thumbbutton.dwFlags |= THBF.NONINTERACTIVE;
                        }
                        if (thumbButtonInfo.DismissWhenClicked)
                        {
                            thumbbutton.dwFlags |= THBF.DISMISSONCLICK;
                            goto IL_146;
                        }
                        goto IL_146;
                    }
                    goto IL_1AE;
                }
IL_179:
                array[(int) ((UIntPtr) num)] = new THUMBBUTTON
                {
                    iId = num,
                    dwFlags = (THBF.DISABLED | THBF.NOBACKGROUND | THBF.HIDDEN),
                    dwMask = (THB.ICON | THB.TOOLTIP | THB.FLAGS)
                };
                num += 1u;
IL_1AE:
                if (num < 7u)
                {
                    goto IL_179;
                }
                result2 = this._taskbarList.ThumbBarUpdateButtons(this._hwndSource.Handle, (uint) array.Length, array);
            }
            finally
            {
                foreach (THUMBBUTTON thumbbutton2 in array)
                {
                    IntPtr hIcon = thumbbutton2.hIcon;
                    if (IntPtr.Zero != hIcon)
                    {
                        Utility.SafeDestroyIcon(ref hIcon);
                    }
                }
            }
            return result2;
        }

        private const int c_MaximumThumbButtons = 7;

        private static readonly WM WM_TASKBARBUTTONCREATED = NativeMethods.RegisterWindowMessage("TaskbarButtonCreated");

        private static readonly Thickness _EmptyThickness = default(Thickness);

        private SafeGdiplusStartupToken _gdipToken;

        private bool _haveAddedButtons;

        private Window _window;

        private HwndSource _hwndSource;

        private ITaskbarList3 _taskbarList;

        private readonly Size _overlaySize;

        private bool _isAttached;

        public static readonly DependencyProperty TaskbarItemInfoProperty = DependencyProperty.RegisterAttached("TaskbarItemInfo", typeof(TaskbarItemInfo), typeof(TaskbarItemInfo), new PropertyMetadata(null, new PropertyChangedCallback(TaskbarItemInfo._OnTaskbarItemInfoChanged), new CoerceValueCallback(TaskbarItemInfo._CoerceTaskbarItemInfoValue)));

        public static readonly DependencyProperty ProgressStateProperty = DependencyProperty.Register("ProgressState", typeof(TaskbarItemProgressState), typeof(TaskbarItemInfo), new PropertyMetadata(TaskbarItemProgressState.None, delegate (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarItemInfo) d)._OnProgressStateChanged();
        }, (DependencyObject d, object e) => TaskbarItemInfo._CoerceProgressState((TaskbarItemProgressState) e)));

        public static readonly DependencyProperty ProgressValueProperty = DependencyProperty.Register("ProgressValue", typeof(double), typeof(TaskbarItemInfo), new PropertyMetadata(0.0, delegate (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarItemInfo) d)._OnProgressValueChanged();
        }, (DependencyObject d, object e) => TaskbarItemInfo._CoerceProgressValue((double) e)));

        public static readonly DependencyProperty OverlayProperty = DependencyProperty.Register("Overlay", typeof(ImageSource), typeof(TaskbarItemInfo), new PropertyMetadata(null, delegate (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarItemInfo) d)._OnOverlayChanged();
        }));

        public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(TaskbarItemInfo), new PropertyMetadata(string.Empty, delegate (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarItemInfo) d)._OnDescriptionChanged();
        }));

        public static readonly DependencyProperty ThumbnailClipMarginProperty = DependencyProperty.Register("ThumbnailClipMargin", typeof(Thickness), typeof(TaskbarItemInfo), new PropertyMetadata(default(Thickness), delegate (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarItemInfo) d)._OnThumbnailClipMarginChanged();
        }, (DependencyObject d, object e) => TaskbarItemInfo._CoerceThumbnailClipMargin((Thickness) e)));

        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Infos")]
        public static readonly DependencyProperty ThumbButtonInfosProperty = DependencyProperty.Register("ThumbButtonInfos", typeof(ThumbButtonInfoCollection), typeof(TaskbarItemInfo), new PropertyMetadata(null, delegate (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TaskbarItemInfo) d)._OnThumbButtonsChanged();
        }));
    }
}
