using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using IndianHealthService.BMXNet.Util;

namespace IndianHealthService.BMXNet.WinForm
{
    /// <summary>
    /// Stardardized "About" dialog that displays information from the executable's (RootAssembly) AssemblyInfo:
    /// <list>
    /// AssemblyTitle
    /// AssemblyProduct
    /// AssemblyVersion
    /// AssemblyCopyright
    /// AssemblyCompany
    /// AssemblyDescription
    /// </list>
    /// <para>
    /// Additionally, a list box showing all non-system .NET assemblies is displayed.  Set IncludeRoot=True
    /// if the RootAssembly should be included in the list.
    /// </para>
    /// <example>
    /// Usage of dialog:
    /// <code>
    /// AboutDialog dialog=new AboutDialog();
    /// dialog.RootAssembly = Assembly.GetExecutingAssembly();
    /// dialog.IncludeRoot = true;
    /// dialog.Show(this.Parent);    
    /// </code>
    /// By default, the RootAssebmly is the Assembly.GetExecutingAssembly();
    /// </example>
    /// </summary>
    public partial class AboutDialog : Form
    {
        public AboutDialog()
        {
            InitializeComponent();

            //  Initialize the AboutBox to display the product information from the assembly information.
            //  Change assembly information settings for your application through either:
            //  - Project->Properties->Application->Assembly Information
            //  - AssemblyInfo.cs
            this.Text = String.Format("About {0}", EntryAssemblyInfo.AssemblyTitle);
            this.labelProductName.Text = EntryAssemblyInfo.AssemblyProduct;
            this.labelVersion.Text = String.Format("Version {0}", EntryAssemblyInfo.AssemblyVersion);
            this.labelCopyright.Text = EntryAssemblyInfo.AssemblyCopyright;
            this.labelCompanyName.Text = EntryAssemblyInfo.AssemblyCompany;
            this.textBoxDescription.Text = EntryAssemblyInfo.AssemblyDescription;
        }

        private bool _includeRoot = false;

        /// <summary>
        /// Set to True if the RootAssembly should be included in the list of displayed assemblies.  False by default.
        /// </summary>
        public bool IncludeRoot
        {
            get { return _includeRoot; }
            set { _includeRoot = value; }
        }

       private Assembly _rootAssembly = Assembly.GetEntryAssembly();

       /// <summary>
       /// The assembly that all references are followed from.  The EntryAssembly by default.
       /// </summary>
       public Assembly RootAssembly
        {
            get { return _rootAssembly; }
            set { _rootAssembly = value; }
        }

 

        private void AboutDialog_Load(object sender, EventArgs e)
        {
            this.Icon = this.Owner==null ? null : this.Owner.Icon;
      
            Dictionary<String, AssemblyName> dependents = new Dictionary<string, AssemblyName>();
            SortedList<String, String> sortedList = new SortedList<string, string>();

            if (this.IncludeRoot)
            {
                sortedList.Add(this.RootAssembly.GetName().Name, this.RootAssembly.GetName().Version.ToString());
            }

            foreach (AssemblyName each in this.RootAssembly.GetReferencedAssemblies())
            {
                this.AddDependents(dependents, each);
            }

            foreach (AssemblyName each in dependents.Values)
            {
                if (!(each.Name.Equals(this.RootAssembly.GetName().Name) || each.Name.Equals(this.RootAssembly.GetName().Name) || (each.Name.StartsWith("Microsoft") || each.Name.StartsWith("System") || each.Name.StartsWith("mscorlib") || each.Name.StartsWith("Accessibility"))))
                {
                    sortedList.Add(each.Name, each.Version.ToString());
                }
            }

            this.textBoxDescription.Clear();

            foreach (String each in sortedList.Keys)
            {
                this.textBoxDescription.AppendText(each + " (" + sortedList[each] + ")\r\n");
            }       
        }

        private void AddDependents(Dictionary<string, AssemblyName> dependents, AssemblyName anAssemblyName)
        {
            if (dependents.ContainsKey(anAssemblyName.FullName))
                return;

            dependents[anAssemblyName.FullName] = anAssemblyName;

            try
            {
                foreach (AssemblyName each in Assembly.Load(anAssemblyName).GetReferencedAssemblies())
                {
                    this.AddDependents(dependents, each);
                }
            }
            catch
            {

            }
        }

        private void okButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }            
            
    }
}
