text: ﻿using System;
  using System.Diagnostics;
  using System.Threading.Tasks;
  using Bot.Builder.Community.Storage.Elasticsearch;
  using Elasticsearch.Net;
  using Microsoft.Bot.Builder;
  using Microsoft.Extensions.Configuration;
  using Microsoft.VisualStudio.TestTools.UnitTesting;
  using Nest;
  using Nest.JsonNetSerializer;
  
  namespace Bot.Builder.Community.Storage.Tests
  {
      [TestClass]
      public class ElasticsearchStorageTests : StorageBaseTests
      {
          private string elasticsearchEndpoint;
          private IStorage storage;
  
          public ElasticsearchStorageTests() { }
  
          [TestInitialize]
          public void Initialize()
          {
              // Get elasticsearch configuration from external file.
              var config = new ConfigurationBuilder()
                  .AddJsonFile("elasticsearchstoragesettings.json")
                  .Build();
  
              var elasticsearchStorageOptions = new ElasticsearchStorageOptions
              {
                  ElasticsearchEndpoint = new Uri(config["Endpoint"]),
                  UserName = config["UserName"],
                  Password = config["Password"],
                  IndexName = config["IndexName"],
                  IndexMappingDepthLimit = int.Parse(config["IndexMappingDepthLimit"])
              };
  
              elasticsearchEndpoint = config["Endpoint"];
  
              storage = new ElasticsearchStorage(elasticsearchStorageOptions);
          }
  
          [TestCleanup]
          public async Task TestCleanUp()
          {
              if (storage != null)
              {
                  // Get elasticsearch configuration from external file.
                  var config = new ConfigurationBuilder()
                      .AddJsonFile("elasticsearchstoragesettings.json")
                      .Build();
  
                  var elasticsearchStorageOptions = new ElasticsearchStorageOptions
                  {
                      ElasticsearchEndpoint = new Uri(config["Endpoint"]),
                      UserName = config["UserName"],
                      Password = config["Password"],
                      IndexName = config["IndexName"],
                      IndexMappingDepthLimit = int.Parse(config["IndexMappingDepthLimit"])
                  };
                  var connectionPool = new SingleNodeConnectionPool(elasticsearchStorageOptions.ElasticsearchEndpoint);
                  var connectionSettings = new ConnectionSettings(connectionPool, sourceSerializer: JsonNetSerializer.Default);
  
                  if (!string.IsNullOrEmpty(elasticsearchStorageOptions.UserName) && !string.IsNullOrEmpty(elasticsearchStorageOptions.Password))
                  {
                      connectionSettings = connectionSettings.BasicAuthentication(elasticsearchStorageOptions.UserName, elasticsearchStorageOptions.Password);
                  }
  
                  var client = new ElasticClient(connectionSettings);
                  try
                  {
                      await client.Indices.DeleteAsync(Indices.Index(config["IndexName"] + "-" + DateTime.Now.ToString("MM-dd-yyyy")));
                  }
                  catch (Exception ex)
                  {
                      Debug.WriteLine("Error cleaning up resources: {0}", ex.ToString());
                  }
              }
          }
  
          [TestMethod]
          [TestCategory("Storage")]
          [Microsoft.VisualStudio.TestTools.UnitTesting.Ignore("Ignore this test as it requires an Elasticsearch environment to run.")]
          public void Constructor_Should_Throw_Exception_On_InvalidOptions()
          {
              // No Options. Should throw. 
              Assert.ThrowsException<ArgumentNullException>(() => new ElasticsearchStorage(null));
  
              // No Endpoint. Should throw. 
              Assert.ThrowsException<ArgumentNullException>(() => new ElasticsearchStorage(new ElasticsearchStorageOptions
              {
                  UserName = "testUserName",
                  Password = "testPassword",
                  IndexName = "testIndexName",
                  IndexMappingDepthLimit = 100000,
              }));
  
              // No Index name. Should throw. 
              Assert.ThrowsException<ArgumentNullException>(() => new ElasticsearchStorage(new ElasticsearchStorageOptions
              {
                  ElasticsearchEndpoint = new Uri(elasticsearchEndpoint),
                  UserName = "testUserName",
                  Password = "testPassword",
                  IndexMappingDepthLimit = 100000,
              }));
          }
  
          [TestMethod]
          [TestCategory("Storage")]
          [Microsoft.VisualStudio.TestTools.UnitTesting.Ignore("Ignore this test as it requires an Elasticsearch environment to run.")]
          public async Task ElasticsearchStorage_CreateObjectTest()
          {
              await this.CreateObjectTest(storage);
          }
  
          [TestMethod]
          [TestCategory("Storage")]
          [Microsoft.VisualStudio.TestTools.UnitTesting.Ignore("Ignore this test as it requires an Elasticsearch environment to run.")]
          public async Task ElasticsearchStorage_ReadUnknownTest()
          {
              await this.ReadUnknownTest(storage);
          }
  
          [TestMethod]
          [TestCategory("Storage")]
          [Microsoft.VisualStudio.TestTools.UnitTesting.Ignore("Ignore this test as it requires an Elasticsearch environment to run.")]
          public async Task ElasticsearchStorage_UpdateObjectTest()
          {
              await this.UpdateObjectTest(storage);
          }
  
  
          [TestMethod]
          [TestCategory("Storage")]
          [Microsoft.VisualStudio.TestTools.UnitTesting.Ignore("Ignore this test as it requires an Elasticsearch environment to run.")]
          public async Task ElasticsearchStorage_DeleteObjectTest()
          {
              await this.DeleteObjectTest(storage);
          }
  
          [TestMethod]
          [TestCategory("Storage")]
          [Microsoft.VisualStudio.TestTools.UnitTesting.Ignore("Ignore this test as it requires an Elasticsearch environment to run.")]
          public async Task ElasticsearchStorage_HandleCrazyKeys()
          {
              await this.HandleCrazyKeys(storage);
          }
      }
  }
  