context: using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Drawing;
  using System.IO;
  using System.Linq;
  using System.Text;
  using System.Threading;
  using System.Threading.Tasks;
  using System.Windows.Forms;
  using ConEmu.WinForms;
  using GitCommands;
  using GitCommands.Git;
  using GitCommands.Gpg;
  using GitCommands.Repository;
  using GitCommands.Utils;
  using GitUI.CommandsDialogs.BrowseDialog;
  using GitUI.CommandsDialogs.BrowseDialog.DashboardControl;
  using GitUI.CommandsDialogs.WorktreeDialog;
  using GitUI.Hotkey;
  using GitUI.Plugin;
  using GitUI.Properties;
  using GitUI.Script;
  using GitUI.UserControls;
  using GitUI.UserControls.RevisionGridClasses;
  using GitUI.UserControls.ToolStripClasses;
  using GitUIPluginInterfaces;
  using Microsoft.Win32;
  using ResourceManager;
  using Microsoft.WindowsAPICodePack.Taskbar;
  
  namespace GitUI.CommandsDialogs
  {
      public partial class FormBrowse : GitModuleForm, IBrowseRepo
      {
          #region Translation
  
          private readonly TranslationString _stashCount =
              new TranslationString("{0} saved {1}");
          private readonly TranslationString _stashPlural =
              new TranslationString("stashes");
          private readonly TranslationString _stashSingular =
              new TranslationString("stash");
  
          private readonly TranslationString _warningMiddleOfBisect =
              new TranslationString("You are in the middle of a bisect");
          private readonly TranslationString _warningMiddleOfRebase =
              new TranslationString("You are in the middle of a rebase");
          private readonly TranslationString _warningMiddleOfPatchApply =
              new TranslationString("You are in the middle of a patch apply");
  
          private readonly TranslationString _hintUnresolvedMergeConflicts =
              new TranslationString("There are unresolved merge conflicts!");
  
          private readonly TranslationString _noBranchTitle =
              new TranslationString("no branch");
  
          private readonly TranslationString _noSubmodulesPresent =
              new TranslationString("No submodules");
          private readonly TranslationString _topProjectModuleFormat =
              new TranslationString("Top project: {0}");
          private readonly TranslationString _superprojectModuleFormat =
              new TranslationString("Superproject: {0}");
  
          private readonly TranslationString _indexLockCantDelete =
              new TranslationString("Failed to delete index.lock.");
  
          private readonly TranslationString _errorCaption =
              new TranslationString("Error");
          private readonly TranslationString _loading =
              new TranslationString("Loading...");
  
          private readonly TranslationString _noReposHostPluginLoaded =
              new TranslationString("No repository host plugin loaded.");
  
          private readonly TranslationString _noReposHostFound =
              new TranslationString("Could not find any relevant repository hosts for the currently open repository.");
  
          private readonly TranslationString _configureWorkingDirMenu =
              new TranslationString("Configure this menu");
  
          // ReSharper disable InconsistentNaming
          private readonly TranslationString directoryIsNotAValidRepositoryCaption =
              new TranslationString("Open");
  
          private readonly TranslationString directoryIsNotAValidRepository =
              new TranslationString("The selected item is not a valid git repository.\n\nDo you want to abort and remove it from the recent repositories list?");
          // ReSharper restore InconsistentNaming
  
          private readonly TranslationString _updateCurrentSubmodule =
              new TranslationString("Update current submodule");
  
          private readonly TranslationString _pullFetch =
              new TranslationString("Pull - fetch");
          private readonly TranslationString _pullFetchAll =
              new TranslationString("Pull - fetch all");
          private readonly TranslationString _pullMerge =
              new TranslationString("Pull - merge");
          private readonly TranslationString _pullRebase =
              new TranslationString("Pull - rebase");
          private readonly TranslationString _pullOpenDialog =
              new TranslationString("Open pull dialog");
  
          private readonly TranslationString _buildReportTabCaption =
              new TranslationString("Build Report");
          private readonly TranslationString _consoleTabCaption =
              new TranslationString("Console");
  
          private readonly TranslationString _commitButtonText =
              new TranslationString("Commit");
          #endregion
  
          private Dashboard _dashboard;
          private ToolStripItem _rebase;
          private ToolStripItem _bisect;
          private ToolStripItem _warning;
  
          private ThumbnailToolBarButton _commitButton;
          private ThumbnailToolBarButton _pushButton;
          private ThumbnailToolBarButton _pullButton;
          private bool _toolbarButtonsCreated;
          private readonly ToolStripMenuItem _toolStripGitStatus;
          private readonly GitStatusMonitor _gitStatusMonitor;
          private readonly FilterRevisionsHelper _filterRevisionsHelper;
          private readonly FilterBranchHelper _filterBranchHelper;
  
          private CancellationTokenSource _submodulesStatusCts = new CancellationTokenSource();
          private BuildReportTabPageExtension _buildReportTabPageExtension;
          private string _diffTabPageTitleBase = "";
  
          private readonly FormBrowseMenus _formBrowseMenus;
          private ConEmuControl _terminal;
          private readonly SplitterManager _splitterManager = new SplitterManager(new AppSettingsPath("FormBrowse"));
          private readonly IFormBrowseController _controller;
          private readonly ICommitDataManager _commitDataManager;
          private readonly IRepositoryDescriptionProvider _repositoryDescriptionProvider;
          private readonly IAppTitleGenerator _appTitleGenerator;
          private static bool _showRevisionInfoNextToRevisionGrid;
  
          /// <summary>
          /// For VS designer
          /// </summary>
          private FormBrowse()
          {
              InitializeComponent();
              Translate();
          }
  
          public FormBrowse(GitUICommands aCommands, string filter)
              : base(true, aCommands)
          {
              //Save value for commit info panel, may be changed
              _showRevisionInfoNextToRevisionGrid = AppSettings.ShowRevisionInfoNextToRevisionGrid;
              InitializeComponent();
  
              // set tab page images
              {
                  var imageList = new ImageList();
                  CommitInfoTabControl.ImageList = imageList;
                  imageList.ColorDepth = ColorDepth.Depth8Bit;
                  imageList.Images.Add(Resources.IconCommit);
                  imageList.Images.Add(Resources.IconFileTree);
                  imageList.Images.Add(Resources.IconDiff);
                  imageList.Images.Add(Resources.IconKey);
                  CommitInfoTabControl.TabPages[0].ImageIndex = 0;
                  CommitInfoTabControl.TabPages[1].ImageIndex = 1;
                  CommitInfoTabControl.TabPages[2].ImageIndex = 2;
                  CommitInfoTabControl.TabPages[3].ImageIndex = 3;
              }
  
              if (!AppSettings.ShowGpgInformation.ValueOrDefault)
              {
                  CommitInfoTabControl.RemoveIfExists(GpgInfoTabPage);
              }
  
              RevisionGrid.UICommandsSource = this;
              Repositories.LoadRepositoryHistoryAsync();
              Task.Factory.StartNew(PluginLoader.Load)
                  .ContinueWith((task) => RegisterPlugins(), TaskScheduler.FromCurrentSynchronizationContext());
              RevisionGrid.GitModuleChanged += SetGitModule;
              _filterRevisionsHelper = new FilterRevisionsHelper(toolStripRevisionFilterTextBox, toolStripRevisionFilterDropDownButton, RevisionGrid, toolStripRevisionFilterLabel, ShowFirstParent, form: this);
              _filterBranchHelper = new FilterBranchHelper(toolStripBranchFilterComboBox, toolStripBranchFilterDropDownButton, RevisionGrid);
              toolStripBranchFilterComboBox.DropDown += toolStripBranches_DropDown_ResizeDropDownWidth;
              revisionDiff.Bind(RevisionGrid, fileTree);
  
              Translate();
  
              if (AppSettings.ShowGitStatusInBrowseToolbar)
              {
                  _toolStripGitStatus = new ToolStripMenuItem
                  {
                      ImageTransparentColor = Color.Magenta,
                      ImageScaling = ToolStripItemImageScaling.SizeToFit,
                      Margin = new Padding(0, 1, 0, 2)
                  };
                  ICommitIconProvider commitIconProvider = new CommitIconProvider();
  
                  _gitStatusMonitor = new GitStatusMonitor();
                  _gitStatusMonitor.Init(this);
  
                  _gitStatusMonitor.GitStatusMonitorStateChanged += (s, e) =>
                  {
                      var status = e.State;
                      if (status == GitStatusMonitorState.Stopped)
                      {
                          _toolStripGitStatus.Visible = false;
                          _toolStripGitStatus.Text = String.Empty;
                      }
                      else if(status == GitStatusMonitorState.Running)
                      {
                          _toolStripGitStatus.Visible = true;
                      }
                  };
  
                  _gitStatusMonitor.GitWorkingDirectoryStatusChanged += (s, e) => {
                      var status = e.ItemStatuses.ToList();
                      _toolStripGitStatus.Image = commitIconProvider.GetCommitIcon(status);
  
                      if (status.Count == 0)
                          _toolStripGitStatus.Text = _commitButtonText.Text;
                      else
                          _toolStripGitStatus.Text = string.Format(_commitButtonText + " ({0})", status.Count.ToString());
  
                      RevisionGrid.UpdateArtificialCommitCount(status);
                      //The diff filelist is not updated, as the selected diff is unset
                      //_revisionDiff.RefreshArtificial();
                  };
  
                  _toolStripGitStatus.Click += StatusClick;
                  ToolStrip.Items.Insert(ToolStrip.Items.IndexOf(toolStripButton1), _toolStripGitStatus);
                  ToolStrip.Items.Remove(toolStripButton1);
              }
  
              if (!EnvUtils.RunningOnWindows())
              {
                  toolStripSeparator6.Visible = false;
                  PuTTYToolStripMenuItem.Visible = false;
              }
  
              RevisionGrid.SelectionChanged += RevisionGridSelectionChanged;
              _filterRevisionsHelper.SetFilter(filter);
  
  
              HotkeysEnabled = true;
              Hotkeys = HotkeySettingsManager.LoadHotkeys(HotkeySettingsName);
              GitUICommandsChanged += (a, e) =>
              {
                  var oldcommands = e.OldCommands;
                  RefreshPullIcon();
                  oldcommands.PostRepositoryChanged -= UICommands_PostRepositoryChanged;
                  UICommands.PostRepositoryChanged += UICommands_PostRepositoryChanged;
                  oldcommands.BrowseRepo = null;
                  UICommands.BrowseRepo = this;
              };
              if (aCommands != null)
              {
                  RefreshPullIcon();
                  UICommands.PostRepositoryChanged += UICommands_PostRepositoryChanged;
                  UICommands.BrowseRepo = this;
                  _controller = new FormBrowseController(new GitGpgController(() => Module));
                  _commitDataManager = new CommitDataManager(() => Module);
              }
  
              _repositoryDescriptionProvider = new RepositoryDescriptionProvider(new GitDirectoryResolver());
              _appTitleGenerator = new AppTitleGenerator(_repositoryDescriptionProvider);
  
              FillBuildReport();  // Ensure correct page visibility
              RevisionGrid.ShowBuildServerInfo = true;
  
              _formBrowseMenus = new FormBrowseMenus(menuStrip1);
              RevisionGrid.MenuCommands.MenuChanged += (sender, e) => _formBrowseMenus.OnMenuCommandsPropertyChanged();
              SystemEvents.SessionEnding += (sender, args) => SaveApplicationSettings();
  
              FillTerminalTab();
              ManageWorktreeSupport();
          }
  
          private void LayoutRevisionInfo()
          {
              if (_showRevisionInfoNextToRevisionGrid)
              {
                  RevisionInfo.Parent = RevisionsSplitContainer.Panel2;
                  RevisionsSplitContainer.SplitterDistance = RevisionsSplitContainer.Width - 420;
                  RevisionInfo.DisplayAvatarOnRight();
                  CommitInfoTabControl.SuspendLayout();
                  CommitInfoTabControl.RemoveIfExists(CommitInfoTabPage);
                  //Move difftab to left
                  CommitInfoTabControl.RemoveIfExists(DiffTabPage);
                  CommitInfoTabControl.TabPages.Insert(0, DiffTabPage);
                  CommitInfoTabControl.SelectedTab = DiffTabPage;
                  CommitInfoTabControl.ResumeLayout(true);
                  RevisionsSplitContainer.Panel2Collapsed = false;
              }
              else
              {
                  RevisionInfo.DisplayAvatarOnLeft();
                  CommitInfoTabControl.SuspendLayout();
                  CommitInfoTabControl.InsertIfNotExists(0, CommitInfoTabPage);
                  CommitInfoTabControl.ResumeLayout(true);
                  RevisionInfo.Parent = CommitInfoTabControl.Controls[0];
                  RevisionsSplitContainer.Panel2Collapsed = true;
              }
          }
  
          private void ManageWorktreeSupport()
          {
              if (!GitCommandHelpers.VersionInUse.SupportWorktree)
              {
                  createWorktreeToolStripMenuItem.Enabled = false;
              }
              if (!GitCommandHelpers.VersionInUse.SupportWorktreeList)
              {
                  manageWorktreeToolStripMenuItem.Enabled = false;
              }
          }
  
          public FormBrowse(GitUICommands aCommands, string filter, string selectCommit) : this(aCommands, filter)
          {
              if (!string.IsNullOrEmpty(selectCommit))
              {
                  RevisionGrid.SetInitialRevision(GitRevision.CreateForShortSha1(Module, selectCommit));
              }
          }
  
          private new void Translate()
          {
              base.Translate();
              _diffTabPageTitleBase = DiffTabPage.Text;
          }
  
          void UICommands_PostRepositoryChanged(object sender, GitUIBaseEventArgs e)
          {
              this.InvokeAsync(RefreshRevisions);
          }
  
          private void RefreshRevisions()
          {
              if (RevisionGrid.IsDisposed || IsDisposed || Disposing)
              {
                  return;
              }
  
              if (_dashboard == null || !_dashboard.Visible)
              {
                  revisionDiff.ForceRefreshRevisions();
                  RevisionGrid.ForceRefreshRevisions();
                  InternalInitialize(true);
              }
          }
  
          #region IBrowseRepo
          public void GoToRef(string refName, bool showNoRevisionMsg)
          {
              RevisionGrid.GoToRef(refName, showNoRevisionMsg);
          }
  
          #endregion
  
          private void ShowDashboard()
          {
              if (_dashboard == null)
              {
                  _dashboard = new Dashboard();
                  _dashboard.GitModuleChanged += SetGitModule;
                  toolPanel.ContentPanel.Controls.Add(_dashboard);
                  _dashboard.Dock = DockStyle.Fill;
                  _dashboard.SetSplitterPositions();
              }
              else
                  _dashboard.Refresh();
              _dashboard.Visible = true;
              _dashboard.BringToFront();
              _dashboard.ShowRecentRepositories();
          }
  
          private void HideDashboard()
          {
              if (_dashboard != null && _dashboard.Visible)
              {
                  _dashboard.SaveSplitterPositions();
                  _dashboard.Visible = false;
              }
          }
  
          private void BrowseLoad(object sender, EventArgs e)
          {
              if (EnvUtils.RunningOnWindows() && TaskbarManager.IsPlatformSupported)
              {
                  TaskbarManager.Instance.ApplicationId = "GitExtensions";
              }
              SetSplitterPositions();
              HideVariableMainMenuItems();
  
              RevisionGrid.Load();
              _filterBranchHelper.InitToolStripBranchFilter();
  
              Cursor.Current = Cursors.WaitCursor;
              LayoutRevisionInfo();
              InternalInitialize(false);
              RevisionGrid.Focus();
              RevisionGrid.IndexWatcher.Reset();
  
              RevisionGrid.IndexWatcher.Changed += _indexWatcher_Changed;
  
              Cursor.Current = Cursors.Default;
  
  
              try
              {
                  if (AppSettings.PlaySpecialStartupSound)
                  {
                      using (var cowMoo = Resources.cow_moo)
                          new System.Media.SoundPlayer(cowMoo).Play();
                  }
              }
              catch
              {
                  // This code is just for fun, we do not want the program to crash because of it.
              }
          }
  
          void _indexWatcher_Changed(object sender, IndexChangedEventArgs e)
          {
              bool indexChanged = e.IsIndexChanged;
              this.InvokeAsync(() =>
              {
                  RefreshButton.Image = indexChanged && AppSettings.UseFastChecks && Module.IsValidGitWorkingDir()
                                            ? Resources.arrow_refresh_dirty
                                            : Resources.arrow_refresh;
              });
          }
  
          private bool _pluginsLoaded;
          private void LoadPluginsInPluginMenu()
          {
              if (_pluginsLoaded)
                  return;
              foreach (var plugin in LoadedPlugins.Plugins)
              {
                  var item = new ToolStripMenuItem { Text = plugin.Description, Tag = plugin };
                  item.Click += ItemClick;
                  pluginsToolStripMenuItem.DropDownItems.Insert(pluginsToolStripMenuItem.DropDownItems.Count - 2, item);
              }
              _pluginsLoaded = true;
              UpdatePluginMenu(Module.IsValidGitWorkingDir());
          }
  
          /// <summary>
          ///   Execute plugin
          /// </summary>
          private void ItemClick(object sender, EventArgs e)
          {
              var menuItem = sender as ToolStripMenuItem;
  
gt:             if (menuItem == null)