// ----------------------------------------------------------------------------------
// Microsoft Developer & Platform Evangelism
// 
// Copyright (c) Microsoft Corporation. All rights reserved.
// 
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// ----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
// ----------------------------------------------------------------------------------

namespace Microsoft.Samples.WindowsAzureMmc.SnapIn.Forms
{
    using System;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Windows.Forms;
    using Microsoft.ManagementConsole;
    using Microsoft.Samples.WindowsAzureMmc.Model.Storage;
    using Microsoft.Samples.WindowsAzureMmc.SnapIn.Views;

    /// <summary>
    /// Control to present a list of blob container and a list of related blobs
    /// </summary>
    public partial class BlobContainerControl : UserControl
    {

        #region members
        private Collection<AzureBlob> _displayedBlobs;
        private Collection<AzureBlobContainer> _displayedBlobContainers;
        private BlobContainerFormView _blobFormView = null;

        #region Action declarations
        //Action items
        private Microsoft.ManagementConsole.Action _containerProperties = null;
        private Microsoft.ManagementConsole.Action _blobProperties = null;
        private Microsoft.ManagementConsole.Action _browseBlob = null;
        private Microsoft.ManagementConsole.Action _blobUpload = null;
        private Microsoft.ManagementConsole.Action _contUpload = null;
        private Microsoft.ManagementConsole.Action _contDownload = null;
        private Microsoft.ManagementConsole.Action _containerDelete = null;
        private Microsoft.ManagementConsole.Action _blobDelete = null;
        private Microsoft.ManagementConsole.Action _blobDownload = null;
        private ActionGroup _viewContainer = null;
        private ActionGroup _viewBlob = null;
        private ActionSeparator _sepBlob = null;
        private ActionSeparator _sepContainer = null;
        private ActionSeparator _sepViewBlob = null;
        private ActionSeparator _sepViewContainer = null;
        #endregion
        #endregion

        #region Constants
        private const int MIN_COL_SIZE = 40;
        private const int LV_COL_PADDING = 4;

        private const string AUTO_SIZE_CONTAINERS = "Path";
        private const string AUTO_SIZE_BLOBS = "Path";

        private ListViewColumnSorter.Types[] CONTAINERS_LV_TYPES = new ListViewColumnSorter.Types[] { ListViewColumnSorter.Types.String, ListViewColumnSorter.Types.String, ListViewColumnSorter.Types.Date, ListViewColumnSorter.Types.String };
        private ListViewColumnSorter.Types[] BLOBS_LV_TYPES = new ListViewColumnSorter.Types[] { ListViewColumnSorter.Types.String, ListViewColumnSorter.Types.String, ListViewColumnSorter.Types.String, ListViewColumnSorter.Types.Int };
        #endregion

        #region Public event declarations
        /// <summary>
        /// Event raised when the control wants the blobs for a container
        /// </summary>
        public event ActionNamedItemDelegate GetBlobForContainer;
        /// <summary>
        /// Event raised when the controls wants to update a container
        /// </summary>
        public event ActionDelegate UpdateBlobContainer;
        /// <summary>
        /// Event raised when a new container action is triggered
        /// </summary>
        public event ActionDelegate AddNewContainer;
        /// <summary>
        /// Event raised when a blob upload action is triggered
        /// </summary>
        public event ActionNamedItemDelegate UploadBlob;
        /// <summary>
        /// Upload a local path as a new container
        /// </summary>
        public event ActionDelegate UploadContainer;
        /// <summary>
        /// Dowload a blob to the local file system
        /// </summary>
        public event ActionNamedItemWithBlobsDelegate DownloadBlobs;
        /// <summary>
        /// Dowwload a container to the local file system
        /// </summary>
        public event ActionNamedItemDelegate DownloadContainer;
        /// <summary>
        /// Event raised when a delete container action is triggered
        /// </summary>
        public event ActionNamedItemDelegate DeleteContainer;
        /// <summary>
        /// Event raised then a delete blob action is triggered
        /// </summary>
        public event ActionNamedItemDelegate DeleteBlob;
        /// <summary>
        /// Event raised when the user righ-clicks
        /// </summary>
        public event ActionShowRightClickDelegate ShowRightClick;


        #endregion

        #region Constructors & Public Methods

        /// <summary>
        /// Construct the control
        /// </summary>
        public BlobContainerControl()
        {
            InitializeComponent();
            containersLV.ListViewItemSorter = new ListViewColumnSorter();
            blobsLV.ListViewItemSorter = new ListViewColumnSorter();
        }

        /// <summary>
        /// Connect the view and the control
        /// </summary>
        /// <param name="view"></param>
        public void SetupView(FormView view)
        {
            //Add actions

            //Upload Blob
            _blobUpload = new Microsoft.ManagementConsole.Action("Upload BLOB", "Upload a BLOB to the current container");
            _blobUpload.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(blobUpload_Triggered);
            view.SelectionData.ActionsPaneItems.Add(_blobUpload);

            // download a container
            _contDownload = new Microsoft.ManagementConsole.Action("Download Container", "Download a container to a local folder");
            _contDownload.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(contDownload_Triggered);
            view.SelectionData.ActionsPaneItems.Add(_contDownload);

            //Delete Container
            _containerDelete = new Microsoft.ManagementConsole.Action("Delete Container", "Delete the selected container");
            _containerDelete.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(containerDelete_Triggered);
            view.SelectionData.ActionsPaneItems.Add(_containerDelete);

            //Download BLOB
            _blobDownload = new Microsoft.ManagementConsole.Action("Download BLOBs", "Delete the selected BLOBs");
            _blobDownload.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(blobDownload_Triggered);

            //Delete BLOB
            _blobDelete = new Microsoft.ManagementConsole.Action("Delete BLOB", "Delete the selected BLOB");
            _blobDelete.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(blobDelete_Triggered);

            //Add container
            Microsoft.ManagementConsole.Action addContainer = new Microsoft.ManagementConsole.Action("Add Container", "Add a container to Azure");
            addContainer.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(addContainer_Triggered);
            view.ScopeNode.ActionsPaneItems.Add(addContainer);

            // upload a container
            _contUpload = new Microsoft.ManagementConsole.Action("Upload Container", "Upload local folder to create a new container");
            _contUpload.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(contUpload_Triggered);
            view.ScopeNode.ActionsPaneItems.Add(_contUpload);

            view.ScopeNode.ActionsPaneItems.Add(new ActionSeparator());

            // Refresh
            Microsoft.ManagementConsole.Action refreshContainers = new Microsoft.ManagementConsole.Action("Refresh", "Refresh the view");
            refreshContainers.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(refreshContainers_Triggered);
            view.ScopeNode.ActionsPaneItems.Add(refreshContainers);


            //View seperators
            _sepViewBlob = new ActionSeparator();
            //Container view seperator
            _sepViewContainer = new ActionSeparator();
            view.SelectionData.ActionsPaneItems.Add(_sepViewContainer);


            //View Type
            //Setup Container view actions
            _viewContainer = new ActionGroup("View", "Change the view type for the container list");
            //Large Icon
            Microsoft.ManagementConsole.Action largeIconContainer = new Microsoft.ManagementConsole.Action("Large Icon", "Change the view to large icons");
            largeIconContainer.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(largeIconContainer_Click);
            _viewContainer.Items.Add(largeIconContainer);
            //Small Icon
            Microsoft.ManagementConsole.Action smallIconContainer = new Microsoft.ManagementConsole.Action("Small Icon", "Change the view to small icons");
            smallIconContainer.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(smallIconContainer_Click);
            _viewContainer.Items.Add(smallIconContainer);
            //List
            Microsoft.ManagementConsole.Action listContainer = new Microsoft.ManagementConsole.Action("List", "Change the view to list");
            listContainer.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(listContainer_Click);
            _viewContainer.Items.Add(listContainer);
            //Details
            Microsoft.ManagementConsole.Action detailsContainer = new Microsoft.ManagementConsole.Action("Details", "Change the view to details");
            detailsContainer.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(detailsContainer_Click);
            _viewContainer.Items.Add(detailsContainer);
            //tile
            Microsoft.ManagementConsole.Action tileContainer = new Microsoft.ManagementConsole.Action("Tile", "Change the view to tile");
            tileContainer.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(tileContainer_Click);
            _viewContainer.Items.Add(tileContainer);
            view.SelectionData.ActionsPaneItems.Add(_viewContainer);

            //Setup BLOB view actions
            _viewBlob = new ActionGroup("View", "Change the view type for the BLOB list");
            //Large Icon
            Microsoft.ManagementConsole.Action largeIconBlob = new Microsoft.ManagementConsole.Action("Large Icon", "Change the view to large icons");
            largeIconBlob.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(largeIconBlob_Click);
            _viewBlob.Items.Add(largeIconBlob);
            //Small Icon
            Microsoft.ManagementConsole.Action smallIconBlob = new Microsoft.ManagementConsole.Action("Small Icon", "Change the view to small icons");
            smallIconBlob.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(smallIconBlob_Click);
            _viewBlob.Items.Add(smallIconBlob);
            //List
            Microsoft.ManagementConsole.Action listBlob = new Microsoft.ManagementConsole.Action("List", "Change the view to list");
            listBlob.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(listBlob_Click);
            _viewBlob.Items.Add(listBlob);
            //Details
            Microsoft.ManagementConsole.Action detailsBlob = new Microsoft.ManagementConsole.Action("Details", "Change the view to details");
            detailsBlob.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(detailsBlob_Click);
            _viewBlob.Items.Add(detailsBlob);
            //tile
            Microsoft.ManagementConsole.Action tileBlob = new Microsoft.ManagementConsole.Action("Tile", "Change the view to tile");
            tileBlob.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(tileBlob_Click);
            _viewBlob.Items.Add(tileBlob);

            //Container seperator
            _sepContainer = new ActionSeparator();
            view.SelectionData.ActionsPaneItems.Add(_sepContainer);

            //Container properties
            _containerProperties = new Microsoft.ManagementConsole.Action("Properties", "Get the properties for the selected container");
            _containerProperties.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(containerProperties_Triggered);
            view.SelectionData.ActionsPaneItems.Add(_containerProperties);

            //BLOB seperator
            _sepBlob = new ActionSeparator();

            //View BLOB in browser
            _browseBlob = new Microsoft.ManagementConsole.Action("View in Browser", "View the current BLOB in a browser");
            _browseBlob.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(browseBlob_Triggered);


            //BLOB properties
            _blobProperties = new Microsoft.ManagementConsole.Action("Properties", "Get the properties for the selected BLOB");
            _blobProperties.Triggered += new Microsoft.ManagementConsole.Action.ActionEventHandler(blobProperties_Triggered);

            _blobFormView = (BlobContainerFormView)view;
        }
        #endregion

        #region View type handlers
        private void largeIconContainer_Click(object sender, ActionEventArgs e)
        {
            containersLV.View = System.Windows.Forms.View.LargeIcon;
        }

        private void smallIconContainer_Click(object sender, ActionEventArgs e)
        {
            containersLV.View = System.Windows.Forms.View.SmallIcon;
        }

        private void detailsContainer_Click(object sender, ActionEventArgs e)
        {
            containersLV.View = System.Windows.Forms.View.Details;
        }

        private void listContainer_Click(object sender, ActionEventArgs e)
        {
            containersLV.View = System.Windows.Forms.View.List;
        }

        private void tileContainer_Click(object sender, ActionEventArgs e)
        {
            containersLV.View = System.Windows.Forms.View.Tile;
        }

        private void largeIconBlob_Click(object sender, ActionEventArgs e)
        {
            blobsLV.View = System.Windows.Forms.View.LargeIcon;
        }

        private void smallIconBlob_Click(object sender, ActionEventArgs e)
        {
            blobsLV.View = System.Windows.Forms.View.SmallIcon;
        }

        private void detailsBlob_Click(object sender, ActionEventArgs e)
        {
            blobsLV.View = System.Windows.Forms.View.Details;
        }

        private void listBlob_Click(object sender, ActionEventArgs e)
        {
            blobsLV.View = System.Windows.Forms.View.List;
        }

        private void tileBlob_Click(object sender, ActionEventArgs e)
        {
            blobsLV.View = System.Windows.Forms.View.Tile;
        }
        #endregion

        #region BLOB Action Handlers

        /// <summary>
        /// Download BLOBs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void blobDownload_Triggered(object sender, ActionEventArgs e)
        {
            if (blobsLV.SelectedItems.Count > 0)
            {
                Collection<AzureBlob> blobs = getSelectedBlobs();
                if (blobs.Count > 0)
                {
                    AzureBlobContainer container = getSelectedContainer();
                    DownloadBlobs(container.Name, blobs);
                }
            }
        }


        /// <summary>
        /// Delete a BLOB
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void blobDelete_Triggered(object sender, ActionEventArgs e)
        {
            if (blobsLV.SelectedItems.Count == 1)
            {
                AzureBlob blob = getSelectedBlob();
                if (blob != null)
                {
                    if (MessageBox.Show(this, "Are you sure you want to delete this BLOB?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        AzureBlobContainer container = getSelectedContainer();
                        DeleteBlob(blob.Url.AbsolutePath);

                        if (container != null)
                        {
                            GetBlobForContainer(container.Name);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// View a blob in the browser
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void browseBlob_Triggered(object sender, ActionEventArgs e)
        {
            if (blobsLV.SelectedItems.Count == 1)
            {
                AzureBlob blob = getSelectedBlob();

                if (blob != null)
                {
                    if (blob.Container.IsPublic)
                    {
                        try
                        {
                            Process.Start(blob.Url.AbsoluteUri);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(this, "Unable to launch browser for URL '" + blob.Url + "'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        }
                    }
                    else
                    {
                        MessageBox.Show(this, "BLOB Container is not Public so the BLOB cannot be browsed", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }
                }
            }
        }

        /// <summary>
        /// Get and show the properties for a blob
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void blobProperties_Triggered(object sender, ActionEventArgs e)
        {
            if (blobsLV.SelectedItems.Count == 1)
            {
                using (PropertiesViewer prop = new PropertiesViewer(getSelectedBlob(), false))
                {
                    prop.ShowDialog();
                }
            }
        }

        /// <summary>
        /// Upload a blob
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void blobUpload_Triggered(object sender, ActionEventArgs e)
        {
            AzureBlobContainer container = getSelectedContainer();
            if (container != null)
            {
                UploadBlob(container.Name);
                //GetBlobForContainer(container.Name);
            }
        }


        #endregion

        #region Container Action Handlers


        /// <summary>
        /// Upload a container
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contUpload_Triggered(object sender, ActionEventArgs e)
        {
            UploadContainer();
            UpdateBlobContainer();
        }

        /// <summary>
        /// Download a container to disk
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void contDownload_Triggered(object sender, ActionEventArgs e)
        {
            AzureBlobContainer container = getSelectedContainer();
            if (container != null)
                DownloadContainer(container.Name);
        }

        /// <summary>
        /// Delete a container
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void containerDelete_Triggered(object sender, ActionEventArgs e)
        {
            if (containersLV.SelectedItems.Count == 1)
            {
                AzureBlobContainer container = getSelectedContainer();
                if (container != null)
                {
                    if (MessageBox.Show(this, "Are you sure you want to delete this container?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        DeleteContainer(container.Name);
                        UpdateBlobContainer();
                    }
                }
            }
        }

        /// <summary>
        /// Add a new container
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void addContainer_Triggered(object sender, ActionEventArgs e)
        {
            AddNewContainer();
            UpdateBlobContainer();
        }

        /// <summary>
        /// Refresh the view of container
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void refreshContainers_Triggered(object sender, ActionEventArgs e)
        {
            UpdateBlobContainer();
        }

        /// <summary>
        /// View the properties on a container
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void containerProperties_Triggered(object sender, ActionEventArgs e)
        {
            if (containersLV.SelectedItems.Count == 1)
            {
                using (PropertiesViewer prop = new PropertiesViewer(getSelectedContainer(), false))
                {
                    prop.ShowDialog();
                }
            }
        }
        #endregion

        #region List view handlers

        /// <summary>
        /// When a container is selected, tell the view and get the blobs within
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void containersLV_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (containersLV.SelectedItems.Count == 0)
                _blobFormView.SelectionData.Clear();
            if (containersLV.SelectedItems.Count == 1)
            {
                //Get the currently selected container
                AzureBlobContainer container = getSelectedContainer();
                //Update MMC with the current selection information
                _blobFormView.SelectionData.Update(container, false, null, null);
                if (container != null)
                {
                    //Update the title of the selected data menu in the actions pane
                    _blobFormView.SelectionData.DisplayName = "Container: " + container.Name;
                    //Get the blobs in the selected queue
                    GetBlobForContainer(container.Name);
                }
            }
            showContainerActions();
        }

        /// <summary>
        /// When a container is clicked, tell the view to show the correct actions and 
        /// show the context menu if the right mouse button was used
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void containersLV_MouseClick(object sender, MouseEventArgs e)
        {
            //Get the currently selected container
            AzureBlobContainer container = getSelectedContainer();

            //Update MMC with the current selection information
            _blobFormView.SelectionData.Update(container, false, null, null);
            if (container != null)
            {
                //Update the title of the selected data menu in the actions pane
                _blobFormView.SelectionData.DisplayName = "Container: " + container.Name;
                showContainerActions();

                if (e.Button == MouseButtons.Right)
                    ShowRightClick(containersLV.PointToScreen(e.Location));
            }
        }

        /// <summary>
        /// When a blob is selected, tell the view and update the applicable actions
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void blobsLV_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (blobsLV.SelectedItems.Count == 0)
                _blobFormView.SelectionData.Clear();
            if (blobsLV.SelectedItems.Count == 1)
            {
                //Get the currently selected blob
                AzureBlob blob = getSelectedBlob();
                //Update MMC with the current selection information
                _blobFormView.SelectionData.Update(blob, false, null, null);
                if (blob != null)
                {
                    //Update the title of the selected data menu in the actions pane
                    _blobFormView.SelectionData.DisplayName = "BLOB: " + blob.Name;
                }
            }
            showBlobActions();
        }

        /// <summary>
        /// When a blob is clicked update the view an show the actions, if the right button 
        /// is clicked then show the context menu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void blobsLV_MouseClick(object sender, MouseEventArgs e)
        {
            //Get the currently selected blob
            AzureBlob blob = getSelectedBlob();

            //Update MMC with the current selection information
            _blobFormView.SelectionData.Update(blob, false, null, null);
            if (blob != null)
            {
                //Update the title of the selected data menu in the actions pane
                _blobFormView.SelectionData.DisplayName = "BLOB: " + blob.Name;
                showBlobActions();

                if (e.Button == MouseButtons.Right)
                    ShowRightClick(blobsLV.PointToScreen(e.Location));
            }
        }

        /// <summary>
        /// Double click a blob to view it in the browser
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void blobsLV_DoubleClick(object sender, EventArgs e)
        {
            AzureBlob blob = getSelectedBlob();
            if (blob != null)
            {
                browseBlob_Triggered(sender, null);
            }
        }

        /// <summary>
        /// Handle short cut keys for the containers
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void containersLV_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {

            switch (e.KeyData)
            {
                case Keys.F5:
                    refreshContainers_Triggered(sender, null);
                    break;

                case (Keys.Return | Keys.Alt):
                    containerProperties_Triggered(sender, null);
                    break;

                case Keys.Delete:
                    containerDelete_Triggered(sender, null);
                    break;
            }
        }


        /// <summary>
        /// Handle short cut keys for the blobs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void blobsLV_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.F5:
                    refreshContainers_Triggered(sender, null);
                    break;

                case (Keys.Return | Keys.Alt):
                    blobProperties_Triggered(sender, null);
                    break;

                case Keys.Delete:
                    blobDelete_Triggered(sender, null);
                    break;

            }
        }

        /// <summary>
        /// Handle the size changed event for the container list, to resize the auto size column.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void containersLV_SizeChanged(object sender, EventArgs e)
        {
            //Initialise the variable required
            int totalColumnWidth = 0;
            int autoSizeColumnIndex = 0;

            foreach (ColumnHeader col in containersLV.Columns)
            {
                //Set the link to the index of the column to resize
                if (col.Text.Equals(AUTO_SIZE_CONTAINERS)) autoSizeColumnIndex = col.Index;
                //Update the total width with the current column
                totalColumnWidth += col.Width;
            }

            //Find the difference in the current width of the listview(including padding) and the width of all the columns
            int widthDiff = containersLV.Width - totalColumnWidth - LV_COL_PADDING;
            //Resize the resizable column to make it fit
            int colWidth = containersLV.Columns[autoSizeColumnIndex].Width + widthDiff;
            containersLV.Columns[autoSizeColumnIndex].Width = MIN_COL_SIZE > colWidth ? MIN_COL_SIZE : colWidth;
        }

        /// <summary>
        /// Handle the size changed event for the blob list, to resize the auto size column.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void blobsLV_SizeChanged(object sender, EventArgs e)
        {
            //Initialise the variable required
            int totalColumnWidth = 0;
            int autoSizeColumnIndex = 0;

            foreach (ColumnHeader col in blobsLV.Columns)
            {
                //Set the link to the index of the column to resize
                if (col.Text.Equals(AUTO_SIZE_CONTAINERS)) autoSizeColumnIndex = col.Index;
                //Update the total width with the current column
                totalColumnWidth += col.Width;
            }

            //Find the difference in the current width of the listview(including padding) and the width of all the columns
            int widthDiff = blobsLV.Width - totalColumnWidth - LV_COL_PADDING;
            //Resize the resizable column to make it fit
            int colWidth = blobsLV.Columns[autoSizeColumnIndex].Width + widthDiff;
            blobsLV.Columns[autoSizeColumnIndex].Width = MIN_COL_SIZE > colWidth ? MIN_COL_SIZE : colWidth;
        }

        /// <summary>
        /// Handles the list view column click event, providing functionality to sort.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LV_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Get the currently selected listview
            ListView lvClicked = (ListView)sender;
            // Get the sorter that is being used.
            ListViewColumnSorter lvSorter = (ListViewColumnSorter)lvClicked.ListViewItemSorter;
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvSorter.Order == SortOrder.Ascending)
                {
                    lvSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvSorter.SortColumn = e.Column;
                lvSorter.Order = SortOrder.Ascending;
                // Set the column type for the column that is sorted.
                lvSorter.SortColumnType = lvClicked.Equals(containersLV) ? CONTAINERS_LV_TYPES[e.Column] : BLOBS_LV_TYPES[e.Column];
            }

            // Perform the sort with these new sort options.
            lvClicked.Sort();

        }
        #endregion

        #region Properties

        /// <summary>
        /// The blobs currently displayed
        /// </summary>
        public Collection<AzureBlob> DisplayedBlobs
        {
            get
            {
                return _displayedBlobs;
            }
            set
            {
                _displayedBlobs = value;
                this.blobsLV.Items.Clear();
                if (_displayedBlobs != null)
                {
                    foreach (AzureBlob blob in _displayedBlobs)
                    {
                        ListViewItem li = this.blobsLV.Items.Add(new ListViewItem(new string[] { blob.Name, blob.Url.AbsoluteUri, blob.ContentType, (blob.Size / 1024).ToString() }, 2));
                        li.Tag = blob;
                    }
                }
                this.blobsLV.Refresh();
            }
        }

        /// <summary>
        /// The containers currently displayed
        /// </summary>
        public Collection<AzureBlobContainer> DisplayedBlobContainers
        {
            get
            {
                return _displayedBlobContainers;
            }
            set
            {
                _displayedBlobContainers = value;
                this.containersLV.Items.Clear();
                if (_displayedBlobContainers != null)
                {
                    foreach (AzureBlobContainer container in _displayedBlobContainers)
                    {
                        ListViewItem li = this.containersLV.Items.Add(new ListViewItem(new string[] { container.Name, container.Url.AbsoluteUri, container.LastWriteTimeUtc.ToString("g"), container.IsPublic ? "Yes" : "No" }, 1));
                        li.Tag = container;
                    }
                }
                this.containersLV.Refresh();
                this.blobsLV.Items.Clear();
                _blobFormView.SelectionData.Clear();
            }
        }
        #endregion

        #region private methods

        /// <summary>
        /// Get the currently selected container
        /// </summary>
        /// <returns></returns>
        private AzureBlobContainer getSelectedContainer()
        {
            if (containersLV.SelectedItems.Count > 0)
                return containersLV.SelectedItems[0].Tag as AzureBlobContainer;

            return null;
        }

        /// <summary>
        /// Get the currently selected blob
        /// </summary>
        /// <returns></returns>
        private AzureBlob getSelectedBlob()
        {
            if (blobsLV.SelectedItems.Count > 0)
                return blobsLV.SelectedItems[0].Tag as AzureBlob;

            return null;
        }

        /// <summary>
        /// Get the currently selected blobs
        /// </summary>
        /// <returns></returns>
        private Collection<AzureBlob> getSelectedBlobs()
        {
            Collection<AzureBlob> blobs = new Collection<AzureBlob>();
            if (blobsLV.SelectedItems.Count > 0)
            {
                foreach (ListViewItem lvi in blobsLV.SelectedItems)
                {
                    blobs.Add(lvi.Tag as AzureBlob);
                }
            }

            return blobs;
        }


        /// <summary>
        /// Show the actions for the selected container
        /// </summary>
        private void showContainerActions()
        {
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_blobUpload)) _blobFormView.SelectionData.ActionsPaneItems.Add(_blobUpload);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_contDownload)) _blobFormView.SelectionData.ActionsPaneItems.Add(_contDownload);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_containerDelete)) _blobFormView.SelectionData.ActionsPaneItems.Add(_containerDelete);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_sepViewContainer)) _blobFormView.SelectionData.ActionsPaneItems.Add(_sepViewContainer);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_viewContainer)) _blobFormView.SelectionData.ActionsPaneItems.Add(_viewContainer);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_sepContainer)) _blobFormView.SelectionData.ActionsPaneItems.Add(_sepContainer);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_containerProperties)) _blobFormView.SelectionData.ActionsPaneItems.Add(_containerProperties);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_browseBlob)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_browseBlob);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_blobDownload)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_blobDownload);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_blobDelete)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_blobDelete);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_sepViewBlob)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_sepViewBlob);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_viewBlob)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_viewBlob);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_sepBlob)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_sepBlob);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_blobProperties)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_blobProperties);
        }

        /// <summary>
        /// Show the actions for the selected blob
        /// </summary>
        private void showBlobActions()
        {
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_blobUpload)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_blobUpload);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_contDownload)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_contDownload);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_containerDelete)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_containerDelete);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_sepContainer)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_sepViewContainer);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_viewContainer)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_viewContainer);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_sepContainer)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_sepContainer);
            if (_blobFormView.SelectionData.ActionsPaneItems.Contains(_containerProperties)) _blobFormView.SelectionData.ActionsPaneItems.Remove(_containerProperties);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_browseBlob)) _blobFormView.SelectionData.ActionsPaneItems.Add(_browseBlob);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_blobDownload)) _blobFormView.SelectionData.ActionsPaneItems.Add(_blobDownload);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_blobDelete)) _blobFormView.SelectionData.ActionsPaneItems.Add(_blobDelete);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_sepBlob)) _blobFormView.SelectionData.ActionsPaneItems.Add(_sepViewBlob);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_viewBlob)) _blobFormView.SelectionData.ActionsPaneItems.Add(_viewBlob);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_sepBlob)) _blobFormView.SelectionData.ActionsPaneItems.Add(_sepBlob);
            if (!_blobFormView.SelectionData.ActionsPaneItems.Contains(_blobProperties)) _blobFormView.SelectionData.ActionsPaneItems.Add(_blobProperties);
        }
        #endregion





    }
}