/* Copyright (c) Citrix Systems, Inc. 
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met: 
 * 
 * *   Redistributions of source code must retain the above 
 *     copyright notice, this list of conditions and the 
 *     following disclaimer. 
 * *   Redistributions in binary form must reproduce the above 
 *     copyright notice, this list of conditions and the 
 *     following disclaimer in the documentation and/or other 
 *     materials provided with the distribution. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using XenAdmin.Core;
using System.Drawing;


/*
 * This class provides the option of including an extra image on a menu item
 * after the text.
 * ToolStripMenuItems do not take their width from get preferred size, it is
 * necessary to pad the text with blank characters so the second image can be
 * drawn.
 * 
 * Assumes all menu items are in the same menu for alignment.
 * 
 * 
 */
 
namespace XenAdmin.Controls
{
    public class VisualMenuItem : ToolStripMenuItem
    {

        private static int leftMargin = 35;
        private static int topMargin = 4;
        private static int imagePadding = 5;

        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
                UpdateWidths();
                VisualMenuItemAlignData.Refresh();
                RefreshPadding();
            }
        }

        private double starRating = 0;
        public double StarRating
        {
            get { return starRating; }
            set { starRating = value; }
        }

        private int textWidth = 0;
        public int TextWidth
        {
            get { return textWidth; }
        }

        private Image secondImage;
        public Image SecondImage
        {
            get { return secondImage; }
            set
            {
                secondImage = value;
                VisualMenuItemAlignData.Refresh();
                RefreshPadding();
                this.Invalidate();
            }
        }

        public VisualMenuItem()
        {
        }

        public VisualMenuItem(string Text)
            : base(Text)
        {
            // spacePadding will be set when text is assigned
        }

        public VisualMenuItem(string Text, Image Image)
            : base(Text, Image)
        {
            // spacePadding will be set when text/image is assigned
        }

        private string spacePadding = "";


        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (secondImage == null)
                return;
            e.Graphics.DrawImage(secondImage,
                   leftMargin + VisualMenuItemAlignData.MaxStringLength + imagePadding, 
                   topMargin, secondImage.Width, secondImage.Height);

        }

        protected override void OnParentChanged(ToolStrip oldParent, ToolStrip newParent)
        {
            base.OnParentChanged(oldParent, newParent);
            if (HasAlignData())
            {
                VisualMenuItemAlignData.Refresh();
            }
            RefreshPadding();
        }

        private void UpdateWidths()
        {
            textWidth = Drawing.MeasureText(base.Text.TrimEnd(), this.Font).Width;
        }

        private bool HasAlignData()
        {
            // at the moment we just use a single static object, so no need to distinguish instance ownership
            return true;
        }

        public void RefreshPadding()
        {
            spacePadding = "";
            if (HasAlignData())
            {
                while (textWidth + Drawing.MeasureText(spacePadding, this.Font).Width < VisualMenuItemAlignData.MaxCombinedWidth)
                {
                    spacePadding += " ";
                }
            }
            base.Text = base.Text.TrimEnd();
            base.Text += spacePadding;
        }

        public int ImageWidth()
        {
            if (secondImage == null)
            {
                return 0;
            }
            return (secondImage.Width + imagePadding * 2);
        }
    }

    public static class VisualMenuItemAlignData
    {
        private static ToolStripMenuItem parentStrip;
        public static ToolStripMenuItem ParentStrip
        {
            get { return parentStrip; }
            set
            {
                parentStrip = value;
                Refresh();
            }
        }

        private static int maxStringLength;
        public static int MaxStringLength
        {
            get { return maxStringLength; }
        }

        private static int maxCombinedWidth;
        public static int MaxCombinedWidth
        {
            get { return maxCombinedWidth; }
        }

        private static Object locker = new Object();

        public static void Refresh()
        {
            maxCombinedWidth = 0;
            maxStringLength = 0;
            if (parentStrip == null)
            {
                return;
            }
            lock (locker)
            {
                int maxImageWidth = 0;
                foreach (ToolStripItem item in parentStrip.DropDownItems)
                {
                    VisualMenuItem visItem;
                    if ((visItem = item as VisualMenuItem) != null)
                    {
                        int w = visItem.ImageWidth();
                        if (w > maxImageWidth)
                        {
                            maxImageWidth = w;
                        }
                        if (visItem.TextWidth > maxStringLength)
                        {
                            maxStringLength = visItem.TextWidth;
                        }
                    }
                }
                maxCombinedWidth = maxImageWidth + maxStringLength;
            }     
        }
    }
    
}
