/// <summary>
        /// Adds addins to the ribbon.
        /// </summary>
        /// <param name="addins"></param>
        public void InstallUpdateAddins(ObservableCollection <AddinWrapper> addins)
        {
            foreach (var addin in addins)
            {
                if (!addin.IsSelected)
                {
                    continue;
                }

                // (Konrad) Currently the only way to distinguish between ExternalCommands and ExternalApplications
                // is via "ButtonText" attribute. It should be empty for ExternalApplications.
                if (string.IsNullOrEmpty(addin.ButtonText))
                {
                    // no UI addin
                    // move the addin file
                    if (File.Exists(InstallDirectory + Path.GetFileName(addin.AddinFilePath)))
                    {
                        try
                        {
                            File.Delete(InstallDirectory + Path.GetFileName(addin.AddinFilePath));
                        }
                        catch
                        {
                            Log.AppendLog(LogMessageType.ERROR, "Could not delete Addin File. Moving on.");
                        }
                    }
                    File.Copy(TempDirectory + Path.GetFileName(addin.AddinFilePath), InstallDirectory + Path.GetFileName(addin.AddinFilePath));

                    if (!Directory.Exists(
                            InstallDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name))
                    {
                        Directory.CreateDirectory(
                            InstallDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name);
                        CopyAll(TempDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name,
                                InstallDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name);
                    }
                    else
                    {
                        CopyAll(TempDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name,
                                InstallDirectory + new DirectoryInfo(addin.BetaResourcesPath).Name);
                    }

                    // (Konrad) We are using Idling event here for the reason that depending on order
                    // at which these buttons are installed or added to the ribbon, at the moment that
                    // we are adding this particular tool, it could not be ready on the ribbon yet,
                    // button variable will be null and we won't be able to disable it.
                    AppCommand.EnqueueTask(app =>
                    {
                        var panel = app.GetRibbonPanels("  HOK - Beta").FirstOrDefault(x => x.Name == addin.Panel);
                        if (panel != null && addin.AdditionalButtonNames != null)
                        {
                            var splits = addin.AdditionalButtonNames.Split(';');
                            foreach (var name in splits)
                            {
                                var button = panel.GetItems().FirstOrDefault(x => x.Name == name);
                                if (button != null)
                                {
                                    button.Enabled = false;
                                    panel.Visible  = panel.GetItems().Any(x => x.Visible);
                                }
                            }
                        }
                    });
                }
                else
                {
                    var app    = AppCommand.Instance.m_app;
                    var panel  = app.GetRibbonPanels("  HOK - Beta").FirstOrDefault(x => x.Name == addin.Panel);
                    var button = panel?.GetItems().FirstOrDefault(x => x.ItemText == addin.ButtonText);
                    if (button != null)
                    {
                        button.Visible = true;
                        button.Enabled = false;
                        panel.Visible  = panel.GetItems().Any(x => x.Visible);
                        ((PushButton)button).AssemblyName = InstallDirectory + addin.DllRelativePath;
                    }
                }

                // Reset installed version flag to update datagrid control
                addin.InstalledVersion = addin.Version;
                addin.IsInstalled      = true;
            }
        }
        /// <summary>
        /// Removes addins from the ribbon.
        /// </summary>
        /// <param name="addins"></param>
        public void UninstallAddins(ObservableCollection <AddinWrapper> addins)
        {
            foreach (var addin in addins)
            {
                if (!addin.IsSelected)
                {
                    continue;
                }

                // Reset installed version flag to update datagrid control
                addin.InstalledVersion = "Not installed";
                addin.IsInstalled      = false;

                var app1  = AppCommand.Instance.m_app;
                var panel = app1.GetRibbonPanels("  HOK - Beta").FirstOrDefault(x => x.Name == addin.Panel);

                if (string.IsNullOrEmpty(addin.ButtonText))
                {
                    // no UI addin
                    // remove addin file
                    if (File.Exists(InstallDirectory + Path.GetFileName(addin.AddinFilePath)))
                    {
                        try
                        {
                            File.Delete(InstallDirectory + Path.GetFileName(addin.AddinFilePath));
                        }
                        catch
                        {
                            Log.AppendLog(LogMessageType.ERROR, "Could not delete Addin File. Moving on.");
                        }
                    }

                    // (Konrad) We are using Idling event here for the reason that depending on order
                    // at which these buttons are installed or added to the ribbon, at the moment that
                    // we are adding this particular tool, it could not be ready on the ribbon yet,
                    // button variable will be null and we won't be able to disable it.
                    AppCommand.EnqueueTask(app =>
                    {
                        if (panel != null && addin.AdditionalButtonNames != null)
                        {
                            var splits = addin.AdditionalButtonNames.Split(';');
                            foreach (var name in splits)
                            {
                                var button1 = panel.GetItems().FirstOrDefault(x => x.Name == name);
                                if (button1 != null)
                                {
                                    button1.Visible = false;
                                    panel.Visible   = panel.GetItems().Any(x => x.Visible);
                                }
                            }
                        }
                    });
                }

                // (Konrad) Button needs to be disabled after DLLs were removed since it doesn't work anyways.
                var button = panel?.GetItems().FirstOrDefault(x => x.ItemText == addin.ButtonText);
                if (button != null)
                {
                    button.Visible = false;
                    panel.Visible  = panel.GetItems().Any(x => x.Visible);
                }
            }
        }
        public Result OnStartup(UIControlledApplication application)
        {
            Instance = this;
            m_app    = application;
            var versionNumber = m_app.ControlledApplication.VersionNumber;

            Tasks = new Queue <Action <UIApplication> >();

            application.Idling += OnIdling;

            try
            {
                m_app.CreateRibbonTab(tabName);
            }
            catch
            {
                Log.AppendLog(LogMessageType.WARNING, "Ribbon tab was not created. It might already exist.");
            }

            var panelsVisibility = new Dictionary <string, bool>();

            ViewModel = new AddinInstallerModel(versionNumber);
            foreach (var addin in ViewModel.Addins)
            {
                // (Konrad) Currently the only way to distinguish between ExternalCommands and ExternalApplications
                // is via "ButtonText" attribute. It should be empty for ExternalApplications.
                if (string.IsNullOrEmpty(addin.ButtonText))
                {
                    if (addin.IsInstalled)
                    {
                        if (File.Exists(ViewModel.InstallDirectory + Path.GetFileName(addin.AddinFilePath)))
                        {
                            try
                            {
                                File.Delete(ViewModel.InstallDirectory + Path.GetFileName(addin.AddinFilePath));
                            }
                            catch
                            {
                                Log.AppendLog(LogMessageType.ERROR, "Could not delete existing Addin Manifest.");
                            }
                        }
                        File.Copy(ViewModel.TempDirectory + Path.GetFileName(addin.AddinFilePath), ViewModel.InstallDirectory + Path.GetFileName(addin.AddinFilePath));

                        if (addin.AdditionalButtonNames != null)
                        {
                            if (panelsVisibility.ContainsKey(addin.Panel))
                            {
                                panelsVisibility.Remove(addin.Panel);
                            }

                            panelsVisibility.Add(addin.Panel, true);
                        }
                    }
                    continue;
                }

                // (Konrad) Temp path dll, to file moved from install location
                // Keeps install location free from being locked by Revit.
                // If addin hasn't been installed yet, we create a button for it,
                // but assign it a Temp.dll reference so that we can re-assign it later.
                var relativePath = addin.DllRelativePath.Replace("Temp\\", "");
                var dllPath      = addin.IsInstalled ? ViewModel.InstallDirectory + relativePath : ViewModel.TempDirectory + "Temp.dll";

                var panel = m_app.GetRibbonPanels("  HOK - Beta").FirstOrDefault(x => x.Name == addin.Panel)
                            ?? m_app.CreateRibbonPanel(tabName, addin.Panel);

                var button = (PushButton)panel.AddItem(new PushButtonData(addin.Name + "_Command", addin.ButtonText, dllPath, addin.CommandNamespace));
                button.LargeImage = addin.Image;
                button.ToolTip    = addin.Description;

                button.Visible = addin.IsInstalled;

                if (panelsVisibility.ContainsKey(addin.Panel))
                {
                    if (panelsVisibility[addin.Panel])
                    {
                        panel.Visible = true;
                    }
                }
                else
                {
                    panel.Visible = panel.GetItems().Any(x => x.Visible);
                }
            }

            currentAssembly = Assembly.GetAssembly(GetType()).Location;
            CreateInstallerPanel();

            return(Result.Succeeded);
        }