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

using System;
using System.Windows;
using System.Collections.Generic;
using Haestad.Support.Library;
using Haestad.Support.Support;

namespace Haestad.Framework.UI.Integration
{
    /// <summary>
    /// Class provides general utility methods.
    /// </summary>
    internal sealed class SupportLibrary
    {
        #region Internal Static Methods
        /// <summary>
        /// Method takes two lists of objects that implement INamable and using the Names on those objects, synchronizes the destination
        /// list to the source list. Existing destination objects are preserved. Missing ones are added. Ones not in the source list are
        /// removed from the destination list.
        /// Should NOT be used with long lists for performance reasons (linear lookups).
        /// </summary>
        /// <param name="sourceList">The list that will be used as the template for synchronization.</param>
        /// <param name="destinationList">The list that will be synchronized to the source list.</param>
        internal static void SynchronizeNamedLists(IList<INamable> sourceList, ref IList<INamable> destinationList)
        {
            for (int i = destinationList.Count - 1; i >= 0; i--)
            {
                if (GetIsNamedItemIsMissingFromList(destinationList[i], sourceList))
                    destinationList.RemoveAt(i);
            }

            IList<OrderedINamableWrapper> sortedDestinationList = new List<OrderedINamableWrapper>(destinationList.Count);
            foreach(INamable namableObject in destinationList)
            {
                int index = GetNamedItemListIndex(namableObject, sourceList);
                OrderedINamableWrapper wrapper = new OrderedINamableWrapper(index, namableObject);
                sortedDestinationList.Add(wrapper);
            }

            sortedDestinationList.Sort((item1, item2) => item1.Index.CompareTo(item2.Index));

            for (int i = 0; i < sourceList.Count; i++)
            {
                if (GetIsNamedItemIsMissingFromList(sourceList[i], sortedDestinationList))
                    sortedDestinationList.Insert(i, new OrderedINamableWrapper(i, sourceList[i]));
            }

            destinationList.Clear();
            foreach (OrderedINamableWrapper wrapperObject in sortedDestinationList)
                destinationList.Add(wrapperObject.NamableObject);
        }

        internal static KeyNavSupportFlags AllKeyNavSupportFlagsExceptKeyboardNavigation()
        {
            return KeyNavSupportFlags.Backstage | KeyNavSupportFlags.HotKeys | KeyNavSupportFlags.DialogLaunchers |
                KeyNavSupportFlags.Menus | KeyNavSupportFlags.QuickAccessToolbar | KeyNavSupportFlags.TabsAndControls;
        }

        internal static KeyNavSupportFlags AllKeyNavSupportFlagsExceptBackstage()
        {
            return KeyNavSupportFlags.RibbonNavigation | KeyNavSupportFlags.HotKeys | KeyNavSupportFlags.DialogLaunchers |
                KeyNavSupportFlags.Menus | KeyNavSupportFlags.QuickAccessToolbar | KeyNavSupportFlags.TabsAndControls;
        }
        #endregion

        #region Private Static Methods
        private static bool GetIsNamedItemIsMissingFromList<T>(INamable namableObject, IList<T> listToSearch)
        {
            foreach (INamable searchObject in listToSearch)
            {
                if (searchObject.Name == namableObject.Name)
                    return false;
            }

            return true;
        }

        private static int GetNamedItemListIndex(INamable namableObject, IList<INamable> listToSearch)
        {
            for (int i = 0; i < listToSearch.Count; i++)
            {
                if (listToSearch[i].Name == namableObject.Name)
                    return i;
            }

            throw new Exception("Item not found in list in SupportLibrary::GetNamedItemListIndex()"); // I18N. OK.
        }
        #endregion
    }
}
