// ----------------------------------------------------------------------------------
// 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
{
    using System;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Windows.Forms;
    using Microsoft.ManagementConsole;
    using Microsoft.Samples.WindowsAzureMmc.Model.Storage;
    using Microsoft.Samples.WindowsAzureMmc.SnapIn.Nodes;

    [SnapInSettings("bc834fe5-9953-4d29-ad88-b2a4322bc252",
      DisplayName = "Windows Azure Services Manager",
      Description = "Manage the Hosted and Storage Services for Microsoft Azure Platform")]
    public class AzureManagerSnapIn : SnapIn
    {
        private const int MAXMESSAGESTOPEEK = 32;
        private ErrorHandlingService errorHandler;
        private StorageExplorerNode storageNode;
        private PendingOperationsNode operationsLogNode;
        private ExecutionEngine executor;

        public AzureManagerSnapIn()
            : this(new ErrorHandlingService(), ExecutionEngine.Instance)
        {
        }

        public AzureManagerSnapIn(ErrorHandlingService errorHandler, ExecutionEngine executor)
        {
            // Instantiate nodes.
            this.storageNode = new StorageExplorerNode();
            this.operationsLogNode = new PendingOperationsNode();

            this.RootNode = new AzureRootNode();
            this.RootNode.Children.Add(this.storageNode);
            this.RootNode.Children.Add(this.operationsLogNode);

            this.errorHandler = errorHandler;
            this.executor = executor;

            // Add images to image library
            this.SmallImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.cloud16);
            this.SmallImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.container16);
            this.SmallImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.file16);
            this.SmallImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.queue16);
            this.SmallImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.azure16);
            this.SmallImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.tasks16);

            this.LargeImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.cloud64);
            this.LargeImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.container64);
            this.LargeImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.file64);
            this.LargeImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.queue64);
            this.LargeImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.azure64);
            this.LargeImages.Add(Microsoft.Samples.WindowsAzureMmc.SnapIn.Properties.Resources.tasks32);
        }


        public Collection<AzureBlob> GetBlobsFromContainer(string containerName)
        {
            Collection<AzureBlob> blobs = new Collection<AzureBlob>();
            if (this.storageNode.PowershellHost != null)
            {
                try
                {
                    using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                    {
                        prg.ActionToPerform = () =>
                        {
                            blobs = this.storageNode.PowershellHost.RetrieveBlobs(containerName, "*");
                        };
                        this.Console.ShowDialog(prg);
                    }
                }
                catch (Exception ex)
                {
                    errorHandler.HandleException(ex);
                }
            }
            else
            {
                MessageBox.Show("No Connection to Azure detected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return blobs;
        }

        public Collection<AzureBlobContainer> GetBlobContainers()
        {
            Collection<AzureBlobContainer> containers = new Collection<AzureBlobContainer>();
            if (this.storageNode.PowershellHost != null)
            {
                try
                {
                    using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                    {
                        prg.ActionToPerform = () =>
                        {
                            containers = this.storageNode.PowershellHost.RetrieveBlobContainers();
                        };
                        this.Console.ShowDialog(prg);
                    }
                }
                catch (Exception ex)
                {
                    errorHandler.HandleException(ex);
                }
            }
            else
            {
                MessageBox.Show("No Connection to Azure detected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return containers;
        }

        public void AddBlobContainer(string containerName, bool isPrivate)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.CreateBlobContainer(containerName, isPrivate);
                    };
                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception e)
            {
                errorHandler.HandleException(e);
            }
        }

        public void UploadBlob(string containerName, string blobName, string fileName, bool overwrite)
        {
            try
            {
                this.executor.ExecuteOperation(() =>
                {
                    Collection<AzureBlob> blobs = this.storageNode.PowershellHost.RetrieveBlobs(containerName, blobName);
                    if (blobs.Count > 0)
                    {
                        AzureBlob blob = blobs[0];
                        if (overwrite)
                        {
                            this.storageNode.PowershellHost.DeleteBlob(blob.Url.AbsolutePath);
                        }
                        else
                        {
                            throw new Exception("A Blob with the same name already exists! Select overwrite or delete it first.");
                        }
                    }

                    this.storageNode.PowershellHost.UploadBlob(containerName, blobName, fileName);
                },
                "Upload Blob",
                string.Format(CultureInfo.InvariantCulture, "From {0} to {1}/{2}", fileName, containerName, blobName));
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public void UploadContainer(string localPath, string containerName, bool isPrivate)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.UploadContainer(localPath, containerName, isPrivate);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public void DownloadBlobs(string containerName, Collection<AzureBlob> blobs, string path)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.DownloadBlobs(containerName, blobs, path);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public void DownloadContainer(string containerName, string path)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.DownloadContainer(containerName, path);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public void DeleteBlob(string blobPath)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.DeleteBlob(blobPath);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public void DeleteContainer(string containerName)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.DeleteBlobContainer(containerName);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public Collection<AzureMessage> GetMessagesFromQueue(string queueName)
        {
            Collection<AzureMessage> messages = new Collection<AzureMessage>();
            if (this.storageNode.PowershellHost != null)
            {
                try
                {
                    if (!string.IsNullOrEmpty(queueName))
                    {
                        using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                        {
                            prg.ActionToPerform = () =>
                            {
                                messages = this.storageNode.PowershellHost.PeekMessages(queueName, MAXMESSAGESTOPEEK, true);
                            };

                            this.Console.ShowDialog(prg);
                        }
                    }
                }
                catch (Exception ex)
                {
                    errorHandler.HandleException(ex);
                }
            }
            else
            {
                MessageBox.Show("No Connection to Azure detected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return messages;
        }

        public Collection<AzureQueue> GetQueues()
        {
            Collection<AzureQueue> queues = new Collection<AzureQueue>();
            if (this.storageNode.PowershellHost != null)
            {
                try
                {
                    using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                    {
                        prg.ActionToPerform = () =>
                        {
                            queues = this.storageNode.PowershellHost.RetrieveQueues();
                        };

                        this.Console.ShowDialog(prg);
                    }
                }
                catch (Exception ex)
                {
                    errorHandler.HandleException(ex);
                }
            }
            else
            {
                MessageBox.Show("No Connection to Azure detected!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return queues;
        }

        public void AddQueue(string queueName)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.CreateQueue(queueName);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public void AddMessage(string queueName, string message)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.CreateMessage(queueName, message);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public void DeleteQueue(string queueName)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.DeleteQueue(queueName);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }

        public void PurgeQueue(string queueName)
        {
            try
            {
                using (Forms.ProgressDialog prg = new Forms.ProgressDialog(this.storageNode.PowershellHost))
                {
                    prg.ActionToPerform = () =>
                    {
                        this.storageNode.PowershellHost.PurgeQueue(queueName);
                    };

                    this.Console.ShowDialog(prg);
                }
            }
            catch (Exception ex)
            {
                errorHandler.HandleException(ex);
            }
        }
    }
}