// ----------------------------------------------------------------------------------
// 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.Configuration
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Win32;
    using System.Security.Cryptography;

  public static class RegistryConfiguration
  {

    #region members

    /// <summary>
    /// User key for encrypting the Azure account keys
    /// </summary>
    static byte[] _entropy = new byte[] { 0x21, 0x05, 0x07, 0x08, 0x27, 0x02, 0x23 };

    #endregion

    /// <summary>
    /// Manage add-in confiug data stored in the registry
    /// </summary>
    /// <param name="baseRegKey">The base registry path for settings</param>
    public static ConfigurationData GetConfiguration(string baseRegKey)
    {
      RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(baseRegKey);
      ConfigurationData data = null;
      try
      {
        data = new ConfigurationData();

        // get the accounts
        RegistryKey accountKeys = registryKey.CreateSubKey("Accounts");

        string[] accountNames = accountKeys.GetSubKeyNames();
        if (accountNames != null)
        {
          foreach (string accountName in accountNames)
          {
            RegistryKey accountKey = accountKeys.CreateSubKey(accountName);
            if (accountKey != null)
            {
              // decrypt the key
              byte[] encryptedKey = (byte[]) accountKey.GetValue(string.Empty);
              byte[] decryptedKey = ProtectedData.Unprotect(encryptedKey, _entropy, DataProtectionScope.CurrentUser);
              string accountKeyString = Encoding.Unicode.GetString(decryptedKey);
              // create an account object 
              Account account = new Account(accountName, accountKeyString);
              data.Accounts.Add(account);

              // each account can have zero or more services
              RegistryKey serviceKeys = accountKey.CreateSubKey("Services");

              string[] serviceNames = serviceKeys.GetSubKeyNames();
              if (serviceNames != null)
              {
                foreach (string serviceName in serviceNames)
                {
                  RegistryKey serviceKey = serviceKeys.CreateSubKey(serviceName);
                  if(serviceKey != null) {

                    string sUrl = serviceKey.GetValue("Url") as string;
                    ServiceTypeEnum st = (ServiceTypeEnum)serviceKey.GetValue("Type", ServiceTypeEnum.Unknown);
                    account.Services.Add(serviceName, new Service(st, sUrl));
                  }
                }
              }
            }
          }
        }
      }
      finally
      {
        // very VERY import to close registry keys - they use a window handle
        if (registryKey != null)
          registryKey.Close();
      }
      return data;
    }

    /// <summary>
    /// Save the configuration data to the registry
    /// </summary>
    /// <param name="data"></param>
    public static void SaveConfiguration(ConfigurationData data, string baseRegKey)
    {

      // start with a clear sub key - required if selecting a connection
      Registry.CurrentUser.DeleteSubKeyTree(baseRegKey);

      RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(baseRegKey);      
      try
      {
        // get the accounts
        RegistryKey accountsKey = registryKey.CreateSubKey("Accounts");

        foreach (Account account in data.Accounts)
        {
          RegistryKey accountKey = accountsKey.CreateSubKey(account.AccountName);

          byte[] keybytes = Encoding.Unicode.GetBytes(account.AccountKey);
          byte[] encryptedKey = ProtectedData.Protect(keybytes, _entropy, DataProtectionScope.CurrentUser);

          accountKey.SetValue(string.Empty, encryptedKey);

          // each account can have zero or more services
          RegistryKey servicesKey = accountKey.CreateSubKey("Services");

          foreach(string serviceName in account.Services.Keys)
          {
            Service service = account.Services[serviceName];
            RegistryKey serviceKey = servicesKey.CreateSubKey(serviceName);
            serviceKey.SetValue("Type", (int)service.ServiceType);
            serviceKey.SetValue("Url", service.Url);
          }
        }
      }
      finally
      {
        registryKey.Close();
      }
    }
  }
}