// RadRibbonToggleSplitButton.cs
// Copyright (c) 2016 Bentley Systems, Incorporated. All Rights Reserved.

using Haestad.Framework.Application;
using Haestad.Framework.Support;
using Haestad.Support.Library;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using Telerik.Windows.Controls;

namespace Haestad.Framework.UI.Integration
{
    /// <summary>
    /// Class that defines a split button that can support a specialized toggle behavior where the button command becomes that of
    /// the previously clicked child menu.
    /// </summary>
    public class RadRibbonToggleSplitButton : RadRibbonSplitButtonEx
    {
        #region Constructor
        public RadRibbonToggleSplitButton(IImageProvider imageProvider, IRibbonCallbacks ribbonCallbacks, bool uniqueNameSpecified)
        {
            ImageProvider = imageProvider;
            RibbonCallbacks = ribbonCallbacks;
            UniqueNameSpecified = uniqueNameSpecified;
        }
        #endregion

        #region Internal Methods
        internal void SetDefaultCommand(IRibbonUICommand ribbonUICommand)
        {
            if (DefaultCommand != null && DefaultCommand.Name == ribbonUICommand.Name)
                return;

            string previousCommandName = DefaultCommand == null ? String.Empty : DefaultCommand.Name;

            DefaultCommand = ribbonUICommand;

            RefreshButtonImage();
            RefreshButtonToolTip();
            RefreshButtonLabel();

            UpdateDefaultCommandRegister(this);

            // Note: <whar> Allow null implementations if notifications are not required.
            if (RibbonCallbacks.ApplicationEventChannel != null)
            {
                RibbonSettingsApplicationChangedData settingsChangeData = new RibbonSettingsApplicationChangedData(Name, previousCommandName, DefaultCommand.Name);
                RibbonCallbacks.ApplicationEventChannel.NotifyApplicationChanged(this, ApplicationChangeType.RibbonSettingsChange, settingsChangeData);
            }
        }
        #endregion

        #region Protected Override Methods
        protected override void OnClick()
        {
            if (DefaultCommand == null)
                base.OnClick();
            else
                DefaultCommand.Execute(null);
        }
        #endregion

        #region Private Methods
        private void RefreshButtonImage()
        {
            if (Size == Telerik.Windows.Controls.RibbonView.ButtonSize.Large)
                LargeImage = ImageProvider.GetImage(true, DefaultCommand.LargeGraphicResourceKey);
            else
                SmallImage = ImageProvider.GetImage(false, DefaultCommand.GraphicResourceKey);
        }

        private void RefreshButtonToolTip()
        {
            TelerikLibrary.SetFrameworkElementToolTip(this, DefaultCommand.GetCleanToolTipTitle(), DefaultCommand.GetCleanToolTipDescription());
        }

        private void RefreshButtonLabel()
        {
            // Note: <whar> The agreed protocol here is that if the menu item's ToolTipTitle is set, then the client will also expect the
            // menu item's text/label (header) to be applied to the button.
            if (!StringLibrary.IsBlank(DefaultCommand.ToolTipTitle))
                Text = DefaultCommand.GetCleanLabel();
        }
        #endregion

        #region Private Static Methods
        /// <summary>
        /// Used to register the default command for NAMED DropDownToggle buttons (implemented by this RadRibbonToggleSplitButton class) so that user 
        /// selections for those buttons can be generically persisted in the Ribbon settings file and loaded next time the application runs.
        /// DOES NOT save state for un-named buttons (buttons where no explicit unique name is provided, meaning the ribbon builder will generate one
        /// automatically), since for persistence purposes we require an immutable control name, in order to be able to restore settings.
        /// </summary>
        /// <param name="button">The RadRibbonToggleSplitButton record the default command for.</param>
        private static void UpdateDefaultCommandRegister(RadRibbonToggleSplitButton button)
        {
            if (button.UniqueNameSpecified)
                DefaultCommandRegister[button.Name] = button.DefaultCommand.Name;
        }
        #endregion

        #region Internal Properties
        internal bool HasNoDefaultCommand
        {
            get { return DefaultCommand == null;  }
        }

        internal IRibbonUICommand DefaultCommand
        {
            get;
            private set;
        }
        #endregion

        #region Internal Static Properties
        /// <summary>
        /// A register of named toggle buttons and their current default commands.
        /// </summary>
        internal static IDictionary<string, string> DefaultCommandRegister
        {
            get
            {
                if (m_defaultCommandRegister == null)
                    m_defaultCommandRegister = new Dictionary<string, string>(DEFAULT_CAPACITY);
                return m_defaultCommandRegister;
            }
        }
        #endregion

        #region Private Properties
        private IImageProvider ImageProvider
        {
            get;
            set;
        }

        private IRibbonCallbacks RibbonCallbacks
        {
            get;
            set;
        }

        private bool UniqueNameSpecified
        {
            get;
            set;
        }
        #endregion

        #region Private Static Fields
        private static IDictionary<string, string> m_defaultCommandRegister;
        #endregion

        #region Private Consts
        private const int DEFAULT_CAPACITY = 16;
        #endregion
    }
}
