// ----------------------------------------------------------------------------------
// 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.Powershell.Host.Tests.Storage
{
    using System;
    using System.Collections.ObjectModel;
    using System.Linq;
    using Microsoft.Samples.WindowsAzureMmc.Model.Storage;
    using Microsoft.Samples.WindowsAzureMmc.Powershell.Host;
    using Microsoft.Samples.WindowsAzureMmc.Powershell.Host.Tests.Helpers;
    using Microsoft.Samples.WindowsAzureMmc.Powershell.Host.Tests.Properties;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class Blobs
    {
        private const string GOODCONTAINERNAME = "btestb";
        private const string NESTEDFOLDERBLOB = "somefolder\\";
        private const string NOTEXISTSCONTAINERNAME = "fredisadog";
        private const string BADCONTAINERNAME = "&$^*&$^^$&*($^&*(";

        private static AzurePSHost host;

        [ClassInitialize()]
        public static void BlobsInitialize(TestContext context)
        {
            host = new AzurePSHost(Settings.Default.Account, Settings.Default.Key, true, new Uri(Settings.Default.BlobServiceUrl), new Uri(Settings.Default.QueueServiceUrl), new PSHostUIForTesting());
        }

        [ClassCleanup()]
        public static void BlobsCleanup()
        {
            ((IDisposable)host).Dispose();
        }

        [TestCleanup]
        public void TestCleanUp()
        {
            host.DeleteBlobContainer(GOODCONTAINERNAME);
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg")]
        public void UploadBlob()
        {
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            host.UploadBlob(GOODCONTAINERNAME, "solutions", "solutions.jpg");

            AzureBlob blob = host.RetrieveBlobs(GOODCONTAINERNAME, "solutions").First();
            Assert.AreEqual<string>("solutions", blob.Name);
            Assert.AreEqual<string>(GOODCONTAINERNAME, blob.Container.Name);
        }

        [TestMethod, DeploymentItem(@"resources\shonibare.jpg"), Ignore]
        public void UploadLongSizeBlob()
        {
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            host.UploadBlob(GOODCONTAINERNAME, "shonibare", "shonibare.jpg");

            AzureBlob blob = host.RetrieveBlobs(GOODCONTAINERNAME, "shonibare").First();
            Assert.AreEqual<string>("shonibare", blob.Name);
            Assert.AreEqual<string>(GOODCONTAINERNAME, blob.Container.Name);
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg")]
        public void UploadBlobToFolderInNewContainer()
        {
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            host.UploadBlob(GOODCONTAINERNAME, NESTEDFOLDERBLOB + "solutions", "solutions.jpg");

            AzureBlob blob = host.RetrieveBlobs(GOODCONTAINERNAME, NESTEDFOLDERBLOB + "solutions").First();

            Assert.AreEqual<string>("solutions", blob.Name);
            Assert.AreEqual<string>(GOODCONTAINERNAME, blob.Container.Name);
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg"), Ignore]
        public void GetBlobsList()
        {
            // make a container to put a blob into
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // upload a blob
            host.UploadBlob(GOODCONTAINERNAME, "solutions", "solutions.jpg");

            // get a list of blobs - there can be only one
            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "*");
            Assert.IsNotNull(blobs, "Could not get any blobs");
            Assert.IsTrue(blobs.Count == 1, "There should be one blob in the container");
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg"), Ignore]
        public void GetBlobsListFromNestedFolder()
        {
            // make a container to put a blob into
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // upload a two blobs
            host.UploadBlob(GOODCONTAINERNAME, "solutions", "solutions.jpg");
            host.UploadBlob(GOODCONTAINERNAME, NESTEDFOLDERBLOB + "solutions", "solutions.jpg");

            // get a list of blobs - there can be only two
            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "*");
            Assert.IsNotNull(blobs, "Could not get any blobs");
            Assert.IsTrue(blobs.Count == 2, "There should be one blob in the container");
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg")]
        public void GetBlob()
        {
            // need to create a container before we can get it
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // upload a blob
            host.UploadBlob(GOODCONTAINERNAME, "solutions", "solutions.jpg");

            // get the blob
            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "solutions");
            Assert.IsNotNull(blobs, "Failed to get blobs");
            Assert.IsTrue(blobs.Count == 1, "Did not find exactly one blob in the container");
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg")]
        public void GetBlobFromNestedFolder()
        {
            // need to create a container before we can get it
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // upload a blob
            host.UploadBlob(GOODCONTAINERNAME, NESTEDFOLDERBLOB + "solutions", "solutions.jpg");

            // get the blob
            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, NESTEDFOLDERBLOB + "solutions");
            Assert.IsNotNull(blobs, "Failed to get blobs");
            Assert.IsTrue(blobs.Count == 1, "Did not find exactly one blob in the container");
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg"), Ignore]
        public void GetAllBlobsInContainerUsingWildcard()
        {
            // need to create a container before we can get it
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // upload a blob
            host.UploadBlob(GOODCONTAINERNAME, "solutions", "solutions.jpg");

            // get the blob
            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "*");
            Assert.IsNotNull(blobs, "Failed to get blobs");
            Assert.IsTrue(blobs.Count == 1, "Did not find exactly one blob in the container");
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg"), Ignore]
        public void GetAllBlobsInContainerFromNestedFolderWithWildcard()
        {
            // need to create a container before we can get it
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // upload a blob
            host.UploadBlob(GOODCONTAINERNAME, NESTEDFOLDERBLOB + "solutions", "solutions.jpg");

            // get the blob
            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "*");
            Assert.IsNotNull(blobs, "Failed to get blobs");
            Assert.IsTrue(blobs.Count == 1, "Did not find exactly one blob in the container");
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg"), Ignore]
        public void GetAllBlobsInContainerWithWildcardThatIncludesNestedFolder()
        {
            // need to create a container before we can get it
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // upload a blob
            host.UploadBlob(GOODCONTAINERNAME, NESTEDFOLDERBLOB + "solutions", "solutions.jpg");

            // get the blob
            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, NESTEDFOLDERBLOB + "*");
            Assert.IsNotNull(blobs, "Failed to get blobs");
            Assert.IsTrue(blobs.Count == 1, "Did not find exactly one blob in the container");
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg"), Ignore]
        public void DeleteBlob()
        {
            // need to create a container before we can delete it
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // upload a blob
            host.UploadBlob(GOODCONTAINERNAME, "solutions", "solutions.jpg");

            // get the blob to make sure it is there before we delete it
            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "solutions");
            Assert.IsNotNull(blobs, "Failed to get blobs");
            Assert.IsTrue(blobs.Count == 1, "Did not find exactly one blob in the container");

            // delete the blob
            host.DeleteBlob(GOODCONTAINERNAME + "/solutions");

            // try to get the blob, this should fail
            blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "solutions.jpg");
            Assert.IsNotNull(blobs, "Failed to get blobs");
            Assert.IsTrue(blobs.Count == 0, "Found blobs in the cotainer when there should be none");
        }

        [TestMethod, DeploymentItem(@"resources\image file with really long bad looking name superkalafridgilisticexpieladocious.jpg"), Ignore]
        public void UploadBlobWithReallyLongFileName()
        {
            // Need to create a container
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            // Create the blob // - no exception is raise by this even though it fails
            host.UploadBlob(GOODCONTAINERNAME, "test", "image file with really long bad looking name superkalafridgilisticexpieladocious.jpg");

            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "*");
            Assert.IsTrue(blobs.Count == 1, "Did not find blobs where there should be one");
        }

        [TestMethod, Ignore]
        [ExpectedException(typeof(System.Management.Automation.ParameterBindingException))]
        public void GetBlobsFromNotExistsContainer()
        {
            Collection<AzureBlob> blobs = host.RetrieveBlobs(NOTEXISTSCONTAINERNAME, "*");
            
            Assert.IsTrue(blobs.Count == 0, "Found non-existant blobs");
        }

        [TestMethod]
        public void GetNotExistsBlobFromExistingContainer()
        {
            // need to create a container
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");

            Collection<AzureBlob> blobs = host.RetrieveBlobs(GOODCONTAINERNAME, "solutions");
            Assert.IsNotNull(blobs, "Collection should not be null");
            Assert.IsTrue(blobs.Count == 0, "Found blobs where there should be none");
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg")]
        public void UploadBlobFileToNonExistingContainer()
        {
            // upload a blob
            host.UploadBlob(BADCONTAINERNAME, "solutions", "solutions.jpg");
            var blobs = host.RetrieveBlobs(BADCONTAINERNAME, "solutions");

            Assert.IsTrue(blobs.Count == 0);
        }

        [TestMethod, DeploymentItem(@"resources\solutions.jpg"), Ignore]
        [ExpectedException(typeof(System.Management.Automation.CmdletProviderInvocationException))]
        public void UploadBlobWithoutOverwrite()
        {
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);
            
            Assert.IsNotNull(container, "Failed to create container");

            host.UploadBlob(GOODCONTAINERNAME, "solutions", "solutions.jpg");
            AzureBlob blob = host.RetrieveBlobs(GOODCONTAINERNAME, "solutions").First();

            Assert.IsNotNull(blob, "Blob upload failed");
            Assert.AreEqual<string>("solutions", blob.Name);
            Assert.AreEqual<string>(GOODCONTAINERNAME, blob.Container.Name);

            // upload the same file again with overwrite off
            host.UploadBlob(GOODCONTAINERNAME, "solutions", "solutions.jpg");

            blob = host.RetrieveBlobs(GOODCONTAINERNAME, "solutions").First();

            Assert.IsNull(blob, "Blob upload succeeded when it should not have");
        }

        [TestMethod]
        [ExpectedException(typeof(System.Management.Automation.CmdletInvocationException))]
        public void UploadNotExistsBlobFileToExistingContainer()
        {
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Container was not created");

            // upload a blob
            host.UploadBlob(GOODCONTAINERNAME, "test", "somemissingfile.jpg");
        }

        [TestMethod]
        [ExpectedException(typeof(System.Management.Automation.ActionPreferenceStopException))]
        public void DeleteNotExistsBlobFromExistingContainer()
        {
            // need to create a container before we can delete it
            host.CreateBlobContainer(GOODCONTAINERNAME, false);
            AzureBlobContainer container = host.RetrieveBlobContainer(GOODCONTAINERNAME);

            Assert.IsNotNull(container, "Failed to create container");
            
            // delete the blob that does not exist
            host.DeleteBlob(GOODCONTAINERNAME + "/solutions.jpg");
            
            // again, this does nothing when maybe it should throw
        }
    }
}