using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using TFSWrappers;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.Proxy;
using Microsoft.TeamFoundation.Build.Proxy;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using TabControl;
using Microsoft.Win32;

namespace TFSBuildManager
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            tcBuildTypes.Items.Clear();
            tsslServer.Text = String.Empty;
            Logon();
        }

        private void LoadBuildTypesTree()
        {
            tvBuildTypes.Nodes.Clear();
            string[] projectNames = serverWrapper.GetProjectNames();
            foreach (string projectName in projectNames)
            {
                TreeNode projectTreeNode = new TreeNode(projectName);
                projectTreeNode.ImageIndex = 0;
                projectTreeNode.SelectedImageIndex = 0;
                string[] buildTypeNames = buildStoreWrapper.GetBuildTypes(projectName);
                if (buildTypeNames.Length > 0)
                {
                    projectTreeNode.Nodes.Add("", "", -1);
                }
                tvBuildTypes.Nodes.Add(projectTreeNode);
            }
        }

        private void Logon()
        {
            string defaultServer = ConfigurationManager.AppSettings[Constants.DefaultServerAppSettingsKey];
            logFileViewer = ConfigurationManager.AppSettings[Constants.LogFileViewerAppSettingsKey];
            buildTypeFileViewer = ConfigurationManager.AppSettings[Constants.BuildTypeFileViewerAppSettingsKey];
            if ((defaultServer != null) && (defaultServer != String.Empty))
            {
                ProgressForm frmProgress = new ProgressForm();
                frmProgress.Show();
                Cursor = Cursors.WaitCursor;
                Application.DoEvents();
                try
                {
                    TFS = TFSFunctions.GetServer(defaultServer);
                }
                finally
                {
                    frmProgress.Close();
                    Cursor = Cursors.Default;
                }
            }
            else
            {
                SelectServer(true);
            }
        }

        private ServerWrapper serverWrapper;
        private SourceControlWrapper sourceControlWrapper;
        private WorkspaceWrapper workspaceWrapper;
        private BuildStoreWrapper buildStoreWrapper;
        private string logFileViewer;
        private string buildTypeFileViewer;

        private TeamFoundationServer tfs;

        public TeamFoundationServer TFS
        {
            get { return tfs; }
            set
            {
                tfs = value;
                if (tfs != null)
                {
                    tsslServer.Text = tfs.Name;
                    if (workspaceWrapper != null)
                    {
                        sourceControlWrapper.DeleteWorkspace(workspaceWrapper.WS.Name);
                    }
                    serverWrapper = new ServerWrapper(tfs);
                    sourceControlWrapper = new SourceControlWrapper(tfs);
                    workspaceWrapper = new WorkspaceWrapper(tfs, sourceControlWrapper.CreateTempWorkspace().Name);
                    buildStoreWrapper = new BuildStoreWrapper(tfs);
                    LoadBuildTypesTree();
                }
                else
                {
                    tsslServer.Text = String.Empty;
                }
            }
        }

        private void tscbGroupBy_SelectedIndexChanged(object sender, EventArgs e)
        {
            BuildTypeTabControlItem item = (BuildTypeTabControlItem)tcBuildTypes.SelectedItem;
            if (item != null)
            {
                if (tscbGroupBy.Text == "Build Status")
                {
                    item.GroupBy(BuildTypeGroupBy.BuildStatus);
                }
                else if (tscbGroupBy.Text == "Build Quality")
                {
                    item.GroupBy(BuildTypeGroupBy.BuildQuality);
                }
                else if (tscbGroupBy.Text == "Complete Date")
                {
                    item.GroupBy(BuildTypeGroupBy.CompleteDate);
                }
            }
            /*BuildTypeTabControlItem item = (BuildTypeTabControlItem)tcBuildTypes.SelectedItem;
            if (item != null)
            {
                Cursor = Cursors.WaitCursor;
                try
                {
                    item.TabListView.Groups.Clear();
                    switch (tscbGroupBy.Text)
                    {
                        case "Build Status":
                            {
                                string[] buildStatuses = BuildStoreWrapper.GetBuildStatuses();
                                foreach (string buildStatus in buildStatuses)
                                {
                                    ListViewGroup listViewGroup = new ListViewGroup(buildStatus, HorizontalAlignment.Left);
                                    listViewGroup.Name = buildStatus.Replace(" ", "");
                                    item.TabListView.Groups.Add(listViewGroup);
                                }
                                foreach (ListViewItem listViewItem in item.TabListView.Items)
                                {
                                    listViewItem.Group = item.TabListView.Groups[((BuildData)listViewItem.Tag).BuildStatus.Replace(" ", "")];
                                }
                                break;
                            }
                        case "Build Quality":
                            {
                                string[] buildQualities = buildStoreWrapper.GetBuildQualities();
                                foreach (string buildQuality in buildQualities)
                                {
                                    ListViewGroup listViewGroup = new ListViewGroup(buildQuality, HorizontalAlignment.Left);
                                    listViewGroup.Name = buildQuality.Replace(" ", "");
                                    item.TabListView.Groups.Add(listViewGroup);
                                }
                                foreach (ListViewItem listViewItem in item.TabListView.Items)
                                {
                                    listViewItem.Group = item.TabListView.Groups[((BuildData)listViewItem.Tag).BuildQuality.Replace(" ", "")];
                                }
                                break;
                            }
                        case "Complete Date":
                            {
                                foreach (ListViewItem listViewItem in item.TabListView.Items)
                                {
                                    BuildData buildData = ((BuildData)listViewItem.Tag);
                                    string groupHeader = buildData.FinishTime.ToShortDateString();
                                    string groupName = "group" + groupHeader.Replace("/", "");
                                    ListViewGroup listViewGroup = item.TabListView.Groups[groupName];
                                    if (listViewGroup == null)
                                    {
                                        listViewGroup = new ListViewGroup(groupHeader, HorizontalAlignment.Left);
                                        listViewGroup.Name = groupName;
                                        item.TabListView.Groups.Add(listViewGroup);
                                    }
                                    listViewItem.Group = listViewGroup;
                                }
                                break;
                            }
                    }
                }
                finally
                {
                    Cursor = Cursors.Default;
                }
            }*/
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OptionsForm frmOptions = new OptionsForm(buildStoreWrapper);
            if (frmOptions.ShowDialog() == DialogResult.OK)
            {
                logFileViewer = frmOptions.LogFileViewer;
                buildTypeFileViewer = frmOptions.BuildTypeFileViewer;
                ConfigurationManager.RefreshSection("AppSettings"); 
            }
        }

        private void newBuildTypeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NewBuildTypeForm frmNewBuildType = new NewBuildTypeForm();
            frmNewBuildType.ShowDialog();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutForm frmAbout = new AboutForm();
            frmAbout.ShowDialog();
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (workspaceWrapper != null)
            {
                sourceControlWrapper.DeleteWorkspace(workspaceWrapper.WS.Name);
            }
        }

        private void DeleteBuildType()
        {
            if (MessageBox.Show("Deleting a build type will remove the build type files from source control.\r\n" +
                "Are you sure that you want to you want to delete \"" + tvBuildTypes.SelectedNode.Text + "\" build type?", "TFSBuildManager", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Cursor = Cursors.WaitCursor;
                try
                {
                    TFSBuildType buildType;
                    BuildTypeTabControlItem item = (BuildTypeTabControlItem)tcBuildTypes.Items.ItemByName(tvBuildTypes.SelectedNode.Text);
                    if (item != null)
                    {
                        buildType = item.TabBuildType;
                    }
                    else
                    {
                        buildType = new TFSBuildType(sourceControlWrapper, workspaceWrapper, buildStoreWrapper, tvBuildTypes.SelectedNode.Parent.Text, tvBuildTypes.SelectedNode.Text);
                    }
                    string buildTypeFolderServerPath = buildType.FileServerPath.Substring(0, 
                        buildType.FileServerPath.LastIndexOf('/'));
                    string buildTypeFolderLocalPath = Path.GetDirectoryName(buildType.FileLocalPath);
                    workspaceWrapper.Delete(buildTypeFolderServerPath, buildTypeFolderLocalPath, "Deleted by TFSBuildManager");
                    workspaceWrapper.ClearFileMapping(buildTypeFolderServerPath);
                    if (item != null)
                    {
                        tcBuildTypes.Items.Remove(item);
                    }
                    else
                    {
                        buildType.Dispose();
                        buildType = null;
                    }
                    tvBuildTypes.SelectedNode.Remove();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error deleting build type. " + ex.Message, "TFSBuildManager",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    Cursor = Cursors.Default;
                }
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DeleteBuildType();
        }

        private void tvBuildTypes_AfterExpand(object sender, TreeViewEventArgs e)
        {
            if ((e.Node.Nodes.Count == 1) && (e.Node.Nodes[0].Text == ""))
            {
                Cursor = Cursors.WaitCursor;
                tvBuildTypes.BeginUpdate();
                try
                {
                    e.Node.Nodes.Clear();
                    TreeNode allBuildTypesTreeNode = new TreeNode(TFSWrappers.Constants.AllBuildTypes);
                    allBuildTypesTreeNode.ImageIndex = 2;
                    allBuildTypesTreeNode.SelectedImageIndex = 2;
                    e.Node.Nodes.Add(allBuildTypesTreeNode);
                    string[] buildTypeNames = buildStoreWrapper.GetBuildTypes(e.Node.Text);
                    foreach (string buildTypeName in buildTypeNames)
                    {
                        TreeNode buildTypeTreeNode = new TreeNode(buildTypeName);
                        buildTypeTreeNode.ImageIndex = 1;
                        buildTypeTreeNode.SelectedImageIndex = 1;
                        e.Node.Nodes.Add(buildTypeTreeNode);
                    }
                }
                finally
                {
                    tvBuildTypes.EndUpdate();
                    Cursor = Cursors.Default;
                }
            }
        }

        private BuildTypeTabControlItem CreateBuildTypeTab(string projectName, string buildTypeName)
        {
            Cursor = Cursors.WaitCursor;
            try
            {
                BuildTypeTabControlItem tabPage = new BuildTypeTabControlItem(sourceControlWrapper, 
                    workspaceWrapper, buildStoreWrapper, projectName, buildTypeName, 
                    tvBuildTypes.SelectedNode, buildTypeFileViewer, logFileViewer);
                tcBuildTypes.Items.Add(tabPage);
                tcBuildTypes.SelectedItem = tabPage;
                return tabPage;
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }

        private void OpenBuildType()
        {
            if (tvBuildTypes.SelectedNode.Level == 1)
            {
                TabControlItem item = tcBuildTypes.Items.ItemByName(tvBuildTypes.SelectedNode.Text.Replace(" ", "_"));
                if (item == null)
                {
                    BuildTypeTabControlItem tabItem = CreateBuildTypeTab(tvBuildTypes.SelectedNode.Parent.Text, tvBuildTypes.SelectedNode.Text);
                    tvBuildTypes.SelectedNode.Tag = tabItem.TabBuildType;
                }
                else
                {
                    tcBuildTypes.SelectedItem = item;
                }
            }
        }

        private void tvBuildTypes_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            OpenBuildType();
        }

        private void SelectServer(bool showProgress)
        {
            DomainProjectPicker domainProjectPicker = new DomainProjectPicker(DomainProjectPickerMode.None);
            if (domainProjectPicker.ShowDialog() == DialogResult.OK)
            {
                ProgressForm frmProgress = new ProgressForm();
                if (showProgress)
                {
                    frmProgress.Show();
                }
                Cursor = Cursors.WaitCursor;
                Application.DoEvents();
                try
                {
                    TFS = domainProjectPicker.SelectedServer;
                }
                finally
                {
                    if (showProgress)
                    {
                        frmProgress.Close();
                    }
                    Cursor = Cursors.Default;
                }
            }
        }

        private void selectServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SelectServer(false);
        }

        private void tsbSelectProject_Click(object sender, EventArgs e)
        {
            SelectServer(false);
        }

        private void tvBuildTypes_AfterSelect(object sender, TreeViewEventArgs e)
        {
            bool isLevel1 = e.Node.Level == 1;
            bool notAllBuildTypes = e.Node.Text != TFSWrappers.Constants.AllBuildTypes;
            openToolStripMenuItem1.Enabled = isLevel1;
            tsbOpenBuildType.Enabled = isLevel1;
            openToolStripMenuItem2.Enabled = isLevel1;
            deleteToolStripMenuItem1.Enabled = isLevel1 && notAllBuildTypes;
            deleteToolStripMenuItem2.Enabled = isLevel1 && notAllBuildTypes;
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenBuildType();
        }

        private void tsbOpenBuildType_Click(object sender, EventArgs e)
        {
            OpenBuildType();
        }

        private void tvBuildTypes_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                tvBuildTypes.SelectedNode = e.Node;
            }
        }

        private void tcBuildTypes_TabControlItemSelectionChanged(TabControlItemChangedEventArgs e)
        {
            tscbGroupBy_SelectedIndexChanged(null, null);
        }

      private void timer_Tick(object sender, EventArgs e)
      {
        if (this.WindowState == FormWindowState.Minimized)
        {
          return;
        }

        BuildTypeTabControlItem item = tcBuildTypes.SelectedItem as BuildTypeTabControlItem;
        if (item == null)
        {
          return;
        }

        item.RefreshView();
      }
    }

    public enum BuildTypeGroupBy
    {
        BuildStatus,
        BuildQuality,
        CompleteDate
    }

    public class BuildTypeTabControlItem : TabControlItem
    {
        public BuildTypeTabControlItem(SourceControlWrapper sourceControlWrapper, 
            WorkspaceWrapper workspaceWrapper, BuildStoreWrapper buildStoreWrapper, 
            string projectName, string buildTypeName, TreeNode tabTreeNode, 
            string buildTypeFileViewer,
            string logFileViewer)
        {
            this.Title = buildTypeName;
            this.Name = buildTypeName.Replace(" ", "_");
            this.tabTreeNode = tabTreeNode;
            this.sourceControlWrapper = sourceControlWrapper;
            this.workspaceWrapper = workspaceWrapper;
            this.buildStoreWrapper = buildStoreWrapper;
            this.projectName = projectName;
            this.buildTypeName = buildTypeName;
            this.buildTypeFileViewer = buildTypeFileViewer;
            this.logFileViewer = logFileViewer;
            

            #region Panel
            Panel panel = new Panel();
            panel.Parent = this;
            panel.BackColor = SystemColors.Info;
            panel.Height = 23;
            panel.Dock = DockStyle.Top;
            panel.BorderStyle = BorderStyle.FixedSingle;
            PictureBox pictureBox = new PictureBox();
            pictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
            pictureBox.Image = Properties.Resources.information;
            pictureBox.Parent = panel;
            pictureBox.Location = new Point(4, 2);
            //Information panel label
            tabLastRefreshedLabel = new Label();
            tabLastRefreshedLabel.AutoSize = true;
            tabLastRefreshedLabel.Text = "Last refreshed at...";
            tabLastRefreshedLabel.Parent = panel;
            tabLastRefreshedLabel.Location = new Point(25, 2);
            #endregion

            #region ToolStrip
            ToolStrip toolStrip = new ToolStrip();

            ToolStripButton refreshToolStripButton = new ToolStripButton("", Properties.Resources.table_refresh, refresh_Click);
            refreshToolStripButton.ToolTipText = "Refresh";
            toolStrip.Items.Add(refreshToolStripButton);

            toolStrip.Items.Add(new ToolStripSeparator());

            executeToolStripButton = new ToolStripButton("", Properties.Resources.control_play_blue, execute_Click);
            executeToolStripButton.ToolTipText = "Execute";
            toolStrip.Items.Add(executeToolStripButton);
            
            customExecuteToolStripButton = new ToolStripButton("", Properties.Resources.application_lightning, customExecute_Click);
            customExecuteToolStripButton.ToolTipText = "Custom Execute";
            toolStrip.Items.Add(customExecuteToolStripButton);

            executeWithoutGetToolStripButton = new ToolStripButton("", Properties.Resources.cog_delete, executeWithoutGet_Click);
            executeWithoutGetToolStripButton.ToolTipText = "Execute Without Get";
            toolStrip.Items.Add(executeWithoutGetToolStripButton);

            stopToolStripButton = new ToolStripButton("", Properties.Resources.stop, stop_Click);
            stopToolStripButton.Enabled = false;
            stopToolStripButton.ToolTipText = "Stop";
            toolStrip.Items.Add(stopToolStripButton);

            toolStrip.Items.Add(new ToolStripSeparator());

            editToolStripButton = new ToolStripButton("", Properties.Resources.application_edit, edit_Click);
            editToolStripButton.ToolTipText = "Edit Build Type";
            toolStrip.Items.Add(editToolStripButton);

            viewFileToolStripButton = new ToolStripButton("", Properties.Resources.page_white_magnify, view_Click);
            viewFileToolStripButton.ToolTipText = "View Build Type File";
            toolStrip.Items.Add(viewFileToolStripButton);

            toolStrip.Items.Add(new ToolStripSeparator());

            changeQualityToolStripButton = new ToolStripButton("", Properties.Resources.accept, changeQuality_Click);
            changeQualityToolStripButton.Enabled = false;
            changeQualityToolStripButton.ToolTipText = "Change Quality";
            toolStrip.Items.Add(changeQualityToolStripButton);

            deleteToolStripButton = new ToolStripButton("", Properties.Resources.delete, delete_Click);
            deleteToolStripButton.Enabled = false;
            deleteToolStripButton.ToolTipText = "Delete";
            toolStrip.Items.Add(deleteToolStripButton);

            exploreDropLocationToolStripButton = new ToolStripButton("", Properties.Resources.folder_explore, exploreDropLocation_Click);
            exploreDropLocationToolStripButton.Enabled = false;
            exploreDropLocationToolStripButton.ToolTipText = "Explore Drop Location";
            toolStrip.Items.Add(exploreDropLocationToolStripButton);

            viewLogFileToolStripButton = new ToolStripButton("", Properties.Resources.information, viewLogFile_Click);
            viewLogFileToolStripButton.Enabled = false;
            viewLogFileToolStripButton.ToolTipText = "View Log File";
            toolStrip.Items.Add(viewLogFileToolStripButton);

            toolStrip.Parent = this;
            #endregion

            #region ContextMenuStrip
            ContextMenuStrip contextMenuStrip = new ContextMenuStrip();
            stopToolStripMenuItem = new ToolStripMenuItem("Stop", Properties.Resources.stop);
            stopToolStripMenuItem.Enabled = false;
            stopToolStripMenuItem.Click += stop_Click;
            contextMenuStrip.Items.Add(stopToolStripMenuItem);
            deleteToolStripMenuItem = new ToolStripMenuItem("Delete", Properties.Resources.delete);
            deleteToolStripMenuItem.Enabled = false;
            deleteToolStripMenuItem.Click += delete_Click;
            contextMenuStrip.Items.Add(deleteToolStripMenuItem);
            changeQualityToolStripMenuItem = new ToolStripMenuItem("Change Quality", Properties.Resources.accept);
            changeQualityToolStripMenuItem.Enabled = false;
            changeQualityToolStripMenuItem.Click += changeQuality_Click;
            contextMenuStrip.Items.Add(changeQualityToolStripMenuItem);
            exploreDropLocationToolStripMenuItem = new ToolStripMenuItem("Explore Drop Location", Properties.Resources.folder_explore);
            exploreDropLocationToolStripMenuItem.Enabled = false;
            exploreDropLocationToolStripMenuItem.Click += exploreDropLocation_Click;
            contextMenuStrip.Items.Add(exploreDropLocationToolStripMenuItem);
            viewLogFileToolStripMenuItem = new ToolStripMenuItem("View Log File", Properties.Resources.information);
            viewLogFileToolStripMenuItem.Enabled = false;
            viewLogFileToolStripMenuItem.Click += viewLogFile_Click;
            contextMenuStrip.Items.Add(viewLogFileToolStripMenuItem);
            #endregion

            #region ImageList
            ImageList imageList = new ImageList();
            imageList.ColorDepth = ColorDepth.Depth32Bit;
            imageList.TransparentColor = Color.Transparent;
            imageList.Images.Add(Properties.Resources.control_play_blue);
            imageList.Images.Add(Properties.Resources.accept);
            imageList.Images.Add(Properties.Resources.exclamation);
            imageList.Images.Add(Properties.Resources.stop);
            #endregion

            #region ListView
            this.tabListView = new ListView();
            tabListView.Parent = this;
            tabListView.Dock = DockStyle.Fill;
            tabListView.View = View.Details;
            tabListView.FullRowSelect = true;
            tabListView.HideSelection = false;
            tabListView.MultiSelect = true;
            tabListView.SmallImageList = imageList;
            tabListView.ContextMenuStrip = contextMenuStrip;
            tabListView.Columns.Add(new ColumnHeader());
            tabListView.Columns.Add(new ColumnHeader());
            tabListView.Columns.Add(new ColumnHeader());
            tabListView.Columns.Add(new ColumnHeader());
            tabListView.Columns[0].Text = "Build Number";
            tabListView.Columns[1].Text = "Build Status";
            tabListView.Columns[2].Text = "Build Quality";
            tabListView.Columns[3].Text = "Completed On";
            tabListView.Columns[0].Width = 200;
            tabListView.Columns[1].Width = 150;
            tabListView.Columns[2].Width = 175;
            tabListView.Columns[3].Width = 250;
            tabListView.Resize += new EventHandler(tabListView_Resize);
            tabListView_Resize(tabListView, new EventArgs());
            tabListView.ColumnClick += new ColumnClickEventHandler(tabListView_ColumnClick);
            tabListView.SelectedIndexChanged += new EventHandler(tabListView_SelectedIndexChanged);
            tabListView.BringToFront();
            listViewColumnSorter = new ListViewColumnSorter();
            tabListView.ListViewItemSorter = listViewColumnSorter;
            #endregion

            #region StatusBar
            StatusStrip statusStrip = new StatusStrip();
            statusStrip.Parent = this;
            statusStrip.Items.Add(new ToolStripStatusLabel("Build Machine:"));           
            tabBuildMachineLabel = new ToolStripStatusLabel("");
            tabBuildMachineLabel.ForeColor = Color.Blue;
            statusStrip.Items.Add(tabBuildMachineLabel);
            statusStrip.Items.Add(new ToolStripStatusLabel("Build Directory:"));
            tabBuildDirectoryLabel = new ToolStripStatusLabel("");
            tabBuildDirectoryLabel.ForeColor = Color.Blue;
            statusStrip.Items.Add(tabBuildDirectoryLabel);
            statusStrip.Items.Add(new ToolStripStatusLabel("Drop Location:"));
            tabDropLocationLabel = new ToolStripStatusLabel("");
            tabDropLocationLabel.ForeColor = Color.Blue;
            statusStrip.Items.Add(tabDropLocationLabel);
            statusStrip.Items.Add(new ToolStripStatusLabel("Status:"));
            tabBuildStatusLabel = new ToolStripStatusLabel("");
            tabBuildStatusLabel.ForeColor = Color.Blue;
            statusStrip.Items.Add(tabBuildStatusLabel);
            #endregion

            RefreshView();

            bool notAllBuildTypes = TabBuildType.Name != TFSWrappers.Constants.AllBuildTypes;
            executeToolStripButton.Enabled = notAllBuildTypes;
            customExecuteToolStripButton.Enabled = notAllBuildTypes;
            executeWithoutGetToolStripButton.Enabled = notAllBuildTypes;
            editToolStripButton.Enabled = notAllBuildTypes;
            viewFileToolStripButton.Enabled = notAllBuildTypes;
        }

        #region Private Fields
        private ToolStripButton executeToolStripButton;
        private ToolStripButton customExecuteToolStripButton;
        private ToolStripButton executeWithoutGetToolStripButton;
        private ToolStripButton editToolStripButton;
        private ToolStripButton viewFileToolStripButton;
        private ToolStripButton stopToolStripButton;
        private ToolStripButton deleteToolStripButton;
        private ToolStripButton changeQualityToolStripButton;
        private ToolStripButton exploreDropLocationToolStripButton;
        private ToolStripButton viewLogFileToolStripButton;
        private ToolStripMenuItem stopToolStripMenuItem;
        private ToolStripMenuItem deleteToolStripMenuItem;
        private ToolStripMenuItem changeQualityToolStripMenuItem;
        private ToolStripMenuItem exploreDropLocationToolStripMenuItem;
        private ToolStripMenuItem viewLogFileToolStripMenuItem;
        private bool initialSortDone;
        private ListViewColumnSorter listViewColumnSorter;
        private SourceControlWrapper sourceControlWrapper;
        private WorkspaceWrapper workspaceWrapper;
        private BuildStoreWrapper buildStoreWrapper;
        private string projectName;
        private string buildTypeName;
        private string buildTypeFileViewer;
        private string logFileViewer;
        #endregion

        #region Properties
        private TreeNode tabTreeNode;

        public TreeNode TabTreeNode
        {
            get { return tabTreeNode; }
        }

        private TFSBuildType tabBuildType;

        public TFSBuildType TabBuildType
        {
            get { return tabBuildType; }
        }

        private ListView tabListView;

        public ListView TabListView
        {
            get { return tabListView; }
        }

        private Label tabLastRefreshedLabel;

        public Label TabLastRefreshedLabel
        {
            get { return tabLastRefreshedLabel; }
        }

        private ToolStripStatusLabel tabBuildMachineLabel;

        public ToolStripStatusLabel TabBuildMachineLabel
        {
            get { return tabBuildMachineLabel; }
        }

        private ToolStripStatusLabel tabBuildStatusLabel;

        public ToolStripStatusLabel TabBuildStatusLabel
        {
            get { return tabBuildStatusLabel; }
        }

        private ToolStripStatusLabel tabBuildDirectoryLabel;

        public ToolStripStatusLabel TabBuildDirectoryLabel
        {
            get { return tabBuildDirectoryLabel; }
        }

        private ToolStripStatusLabel tabDropLocationLabel;

        public ToolStripStatusLabel TabDropLocationLabel
        {
            get { return tabDropLocationLabel; }
        }

        #endregion

        void tabListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool oneOfSelectedBuildsIsRunning = false;
            foreach (ListViewItem listViewItem in TabListView.SelectedItems)
            {
                BuildData buildData = ((BuildData)TabListView.SelectedItems[0].Tag);
                if (buildData.BuildStatusId == 0)
                {
                    oneOfSelectedBuildsIsRunning = true;
                    break;
                }
            }

            int buildStatusId = 0;
            if (TabListView.SelectedItems.Count == 1)
            {
                buildStatusId = ((BuildData)TabListView.SelectedItems[0].Tag).BuildStatusId;
            }

            bool oneBuildSelected = TabListView.SelectedItems.Count == 1;
            bool buildsSelected = TabListView.SelectedItems.Count > 0;
            stopToolStripButton.Enabled = (oneBuildSelected && oneOfSelectedBuildsIsRunning);
            deleteToolStripButton.Enabled = (buildsSelected && !oneOfSelectedBuildsIsRunning);
            changeQualityToolStripButton.Enabled = (buildsSelected && !oneOfSelectedBuildsIsRunning);
            exploreDropLocationToolStripButton.Enabled = oneBuildSelected;
            viewLogFileToolStripButton.Enabled = oneBuildSelected;
            stopToolStripMenuItem.Enabled = (oneBuildSelected && oneOfSelectedBuildsIsRunning);
            deleteToolStripMenuItem.Enabled = (buildsSelected && !oneOfSelectedBuildsIsRunning);
            changeQualityToolStripMenuItem.Enabled = (buildsSelected && !oneOfSelectedBuildsIsRunning);
            exploreDropLocationToolStripMenuItem.Enabled = oneBuildSelected;
            viewLogFileToolStripMenuItem.Enabled = oneBuildSelected;
        }

        void tabListView_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == listViewColumnSorter.SortColumn)
            {
                if (listViewColumnSorter.Order == SortOrder.Ascending)
                {
                    listViewColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    listViewColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                listViewColumnSorter.SortColumn = e.Column;
                listViewColumnSorter.Order = SortOrder.Ascending;
            }
            tabListView.Sort();
        }

        void tabListView_Resize(object sender, EventArgs e)
        {
            ListView listView = (ListView)sender;
            listView.Columns[3].Width = listView.Width - listView.Columns[0].Width - listView.Columns[1].Width - listView.Columns[2].Width - 20;
        }

        private void LoadBuildsList()
        {
            tabListView.Items.Clear();
            if (tabBuildType != null)
            {
                tabListView.BeginUpdate();
                try
                {
                    foreach (BuildData build in tabBuildType.BuildsData)
                    {
                        ListViewItem listViewItem = new ListViewItem();
                        listViewItem.Tag = build;
                        listViewItem.Text = build.BuildNumber;
                        listViewItem.SubItems.Add(build.BuildStatus);
                        listViewItem.SubItems.Add(build.BuildQuality);
                        listViewItem.SubItems.Add(build.FinishTime.ToString());
                        listViewItem.ImageIndex = build.BuildStatusId / 100;
                        tabListView.Items.Add(listViewItem);
                    }
                }
                finally
                {
                    tabListView.EndUpdate();
                }
                if (!initialSortDone)
                {
                    tabListView_ColumnClick(null, new ColumnClickEventArgs(0));
                    tabListView_ColumnClick(null, new ColumnClickEventArgs(0));
                    initialSortDone = true;
                }
                tabListView_SelectedIndexChanged(null, null);
            }
        }

        private void ViewBuildTypeFile()
        {
            try
            {
                if ((buildTypeFileViewer == null) || (buildTypeFileViewer == String.Empty))
                {
                    buildTypeFileViewer = "notepad";
                }
                if (File.Exists(TabBuildType.FileLocalPath))
                {
                    Process.Start(buildTypeFileViewer, TabBuildType.FileLocalPath);
                }
                else
                {
                    MessageBox.Show("Build type file does not exist.", "TFSBuildMnager", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error opening log file. " + ex.Message, "TFSBuildMnager", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void view_Click(object sender, EventArgs e)
        {
            ViewBuildTypeFile();
        }

        private void EditBuildType()
        {
            EditBuildTypeForm frmEditBuildType = new EditBuildTypeForm(sourceControlWrapper.TFS, TabBuildType);
            if (frmEditBuildType.ShowDialog() == DialogResult.OK)
            {
                RefreshView();
            }
        }

        private void edit_Click(object sender, EventArgs e)
        {
            EditBuildType();
        }

        private void ExecuteBuild()
        {
            if (MessageBox.Show("Are you sure that you want to start a build?", "TFSBuildManager",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Cursor = Cursors.WaitCursor;
                try
                {
                    TabBuildType.Execute();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error starting build. " + ex.Message, "TFSBuildMnager", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    Cursor = Cursors.Default;
                    RefreshView();
                }
            }
        }

        private void execute_Click(object sender, EventArgs e)
        {
            ExecuteBuild();
        }

        private void StopBuild()
        {
            BuildData buildData = (BuildData)TabListView.SelectedItems[0].Tag;
            if (MessageBox.Show(String.Format("Are you sure that you want to stop build {0} ?",
                buildData.BuildNumber), "Stop Build", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                string failureMessage = null;
                Cursor = Cursors.WaitCursor;
                try
                {
                    BuildController buildController = (BuildController)sourceControlWrapper.TFS.GetService(typeof(BuildController));
                    buildController.StopBuild(buildData.BuildUri, out failureMessage);
                }
                finally
                {
                    Cursor = Cursors.Default;
                    if (failureMessage != null)
                    {
                        MessageBox.Show(failureMessage, "Stop Build", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    RefreshView();
                }
            }
        }

        private void stop_Click(object sender, EventArgs e)
        {
            StopBuild();
        }

        public void RefreshView()
        {
            if (tabBuildType != null)
            {
                tabBuildType.Dispose();
            }
            tabBuildType = new TFSBuildType(sourceControlWrapper, workspaceWrapper, buildStoreWrapper, projectName, buildTypeName);
            LoadBuildsList();
            tabLastRefreshedLabel.Text = String.Format("Last refreshed on {0}.", DateTime.Now.ToString());
            tabBuildMachineLabel.Text = tabBuildType.BuildMachine.PropertyValue;
            tabBuildStatusLabel.Text = tabBuildType.GetBuildStatus().ToString();
            tabBuildDirectoryLabel.Text = tabBuildType.BuildDirectoryPath.PropertyValue;
            tabDropLocationLabel.Text = tabBuildType.DropLocation.PropertyValue;
        }

        private void refresh_Click(object sender, EventArgs e)
        {
            RefreshView();
        }

        private void DeleteBuilds()
        {
            List<BuildData> buildsData = new List<BuildData>();
            foreach (ListViewItem listViewItem in TabListView.SelectedItems)
            {
                buildsData.Add((BuildData)listViewItem.Tag);
            }
            DeleteBuildsParametersForm frmDeleteBuildsParameters = new DeleteBuildsParametersForm(sourceControlWrapper.TFS, TabBuildType, buildsData.ToArray());
            if (frmDeleteBuildsParameters.ShowDialog() == DialogResult.OK)
            {
                RefreshView();
            }
        }

        private void delete_Click(object sender, EventArgs e)
        {
            DeleteBuilds();
        }

        private void CustomExecute()
        {
            BuildParametersForm frmBuildParameters = new BuildParametersForm(TabBuildType);
            if (frmBuildParameters.ShowDialog() == DialogResult.OK)
            {
                Cursor = Cursors.WaitCursor;
                try
                {
                    TabBuildType.Execute(frmBuildParameters.BuildMachine,
                        frmBuildParameters.DropLocation);
                }
                finally
                {
                    Cursor = Cursors.Default;
                    RefreshView();
                }
            }
        }

        private void customExecute_Click(object sender, EventArgs e)
        {
            CustomExecute();
        }

       private void ChangeQuality()
       {            
            ChangeBuildQualityForm frmUpdateBuildQuality = new ChangeBuildQualityForm(
                TabBuildType.ProjectName, buildStoreWrapper);
            if (frmUpdateBuildQuality.ShowDialog() == DialogResult.OK)
            {
                Cursor = Cursors.WaitCursor;
                try
                {
                    foreach (ListViewItem listViewItem in TabListView.SelectedItems)
                    {
                        BuildData buildData = (BuildData)listViewItem.Tag;
                        buildStoreWrapper.UpdateBuildQuality(TabBuildType.ProjectName, buildData.BuildNumber,
                            frmUpdateBuildQuality.SelectedBuildQuality);
                        listViewItem.SubItems[2].Text = frmUpdateBuildQuality.SelectedBuildQuality;
                    }
                }
                finally
                {
                    Cursor = Cursors.Default;
                }
            }
        }

        private void changeQuality_Click(object sender, EventArgs e)
        {
            ChangeQuality();
        }

        private void ExecuteWithoutGet()
        {
            if (MessageBox.Show("Executing a build without get will set some attributes in the TFSBuild.proj file and will revert them back.\r\n" +
                "Are you sure that you want to you want to continue with this operation?", "TFSBuildManager", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Cursor = Cursors.WaitCursor;
                try
                {
                    TabBuildType.Resumable = true;
                    try
                    {
                        TabBuildType.Execute();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Error starting build. " + ex.Message, "TFSBuildMnager", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    finally
                    {
                        TabBuildType.Resumable = false;
                        RefreshView();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error executing build without get. " + ex.Message, "TFSBuildManager",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    Cursor = Cursors.Default;
                }
            }
        }

        private void executeWithoutGet_Click(object sender, EventArgs e)
        {
            ExecuteWithoutGet();            
        }

        private void ExploreDropLocation()
        {
            try
            {
                BuildData buildData = (BuildData)TabListView.SelectedItems[0].Tag;
                Process.Start("explorer", "/e," + buildData.DropLocation);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error exploring build drop location. " + ex.Message, "TFSBuildMnager", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void exploreDropLocation_Click(object sender, EventArgs e)
        {
            ExploreDropLocation();
        }

        private void ViewLogFile()
        {
            try
            {
                BuildData buildData = (BuildData)TabListView.SelectedItems[0].Tag;                
                if ((logFileViewer == null) || (logFileViewer == String.Empty))
                {
                    logFileViewer = "notepad";
                }
                string logFile = buildData.DropLocation + @"\BuildLog.txt";
                if (File.Exists(logFile))
                {
                    Process.Start(logFileViewer, logFile);
                }
                else
                {
                    MessageBox.Show("Log file does not exist.", "TFSBuildMnager", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error opening log file. " + ex.Message, "TFSBuildMnager", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void viewLogFile_Click(object sender, EventArgs e)
        {
            ViewLogFile();
        }

        public void GroupBy(BuildTypeGroupBy groupBy)
        {
            Cursor = Cursors.WaitCursor;
            try
            {
                TabListView.Groups.Clear();
                switch (groupBy)
                {
                    case BuildTypeGroupBy.BuildStatus:
                        {
                            string[] buildStatuses = BuildStoreWrapper.GetBuildStatuses();
                            foreach (string buildStatus in buildStatuses)
                            {
                                ListViewGroup listViewGroup = new ListViewGroup(buildStatus, HorizontalAlignment.Left);
                                listViewGroup.Name = buildStatus.Replace(" ", "");
                                TabListView.Groups.Add(listViewGroup);
                            }
                            foreach (ListViewItem listViewItem in TabListView.Items)
                            {
                                listViewItem.Group = TabListView.Groups[((BuildData)listViewItem.Tag).BuildStatus.Replace(" ", "")];
                            }
                            break;
                        }
                    case BuildTypeGroupBy.BuildQuality:
                        {
                            string[] buildQualities = buildStoreWrapper.GetBuildQualities();
                            foreach (string buildQuality in buildQualities)
                            {
                                ListViewGroup listViewGroup = new ListViewGroup(buildQuality, HorizontalAlignment.Left);
                                listViewGroup.Name = buildQuality.Replace(" ", "");
                                TabListView.Groups.Add(listViewGroup);
                            }
                            foreach (ListViewItem listViewItem in TabListView.Items)
                            {
                                listViewItem.Group = TabListView.Groups[((BuildData)listViewItem.Tag).BuildQuality.Replace(" ", "")];
                            }
                            break;
                        }
                    case BuildTypeGroupBy.CompleteDate:
                        {
                            foreach (ListViewItem listViewItem in TabListView.Items)
                            {
                                BuildData buildData = ((BuildData)listViewItem.Tag);
                                string groupHeader = buildData.FinishTime.ToShortDateString();
                                string groupName = "group" + groupHeader.Replace("/", "");
                                ListViewGroup listViewGroup = TabListView.Groups[groupName];
                                if (listViewGroup == null)
                                {
                                    listViewGroup = new ListViewGroup(groupHeader, HorizontalAlignment.Left);
                                    listViewGroup.Name = groupName;
                                    TabListView.Groups.Add(listViewGroup);
                                }
                                listViewItem.Group = listViewGroup;
                            }
                            break;
                        }
                }
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
    }
}