Utilities
Utility functions for unit conversion work flows and helper functions.
            
using Autodesk.DesignScript.Runtime;
using Autodesk.ForgeUnits;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Reflection;
namespace DynamoUnits
{
    public static class Utilities
    {
        private static UnitsEngine unitsEngine;
        [SupressImportIntoVM]
        public static string SchemaDirectory { get; set; }
        internal static UnitsEngine ForgeUnitsEngine {
            get {
                if (unitsEngine == null)
                    throw new Exception("There was an issue loading Unit Schemas from the specified path: " + SchemaDirectory);
                return unitsEngine;
            }
        }
        private static string AssemblyDirectory {
            get {
                string location = Assembly.GetExecutingAssembly().Location;
                return Path.GetDirectoryName(location);
            }
        }
        static Utilities()
        {
            SchemaDirectory = Path.Combine(AssemblyDirectory, "unit");
            Initialize();
        }
        internal static void Initialize()
        {
            string location = Assembly.GetExecutingAssembly().Location;
            Configuration configuration = ConfigurationManager.OpenExeConfiguration(location);
            KeyValueConfigurationElement keyValueConfigurationElement = configuration.AppSettings.Settings["schemaPath"];
            string text = null;
            if (keyValueConfigurationElement != null)
                text = keyValueConfigurationElement.Value;
            if (!string.IsNullOrEmpty(text) && Directory.Exists(text))
                SchemaDirectory = text;
            try {
                unitsEngine = new UnitsEngine();
                SchemaUtility.addDefinitionsFromFolder(SchemaDirectory, unitsEngine);
                unitsEngine.resolveSchemas();
            } catch {
                unitsEngine = null;
            }
        }
        internal static void SetTestEngine(string testSchemaDir)
        {
            try {
                unitsEngine = new UnitsEngine();
                SchemaUtility.addDefinitionsFromFolder(testSchemaDir, unitsEngine);
                unitsEngine.resolveSchemas();
            } catch {
                unitsEngine = null;
            }
        }
        public static double ConvertByUnits(double value, Unit fromUnit, Unit toUnit)
        {
            return ForgeUnitsEngine.convert(value, fromUnit.TypeId, toUnit.TypeId);
        }
        [IsVisibleInDynamoLibrary(false)]
        public static double ConvertByUnitIds(double value, string fromUnit, string toUnit)
        {
            return ForgeUnitsEngine.convert(value, fromUnit, toUnit);
        }
        public static double ParseExpressionByUnit(Unit targetUnit, string expression)
        {
            return ForgeUnitsEngine.parse(targetUnit.TypeId, expression);
        }
        [IsVisibleInDynamoLibrary(false)]
        public static double ParseExpressionByUnitId(string targetUnit, string expression)
        {
            return ForgeUnitsEngine.parse(targetUnit, expression);
        }
        public static double ParseExpression(string expression)
        {
            return ForgeUnitsEngine.parseUnitless(expression);
        }
        [IsVisibleInDynamoLibrary(false)]
        public static IEnumerable<Quantity> GetAllQuantities()
        {
            return CovertForgeQuantityDictionaryToCollection(ForgeUnitsEngine.getAllQuantities());
        }
        [IsVisibleInDynamoLibrary(false)]
        public static IEnumerable<Unit> GetAllUnits()
        {
            return ConvertForgeUnitDictionaryToCollection(ForgeUnitsEngine.getAllUnits());
        }
        [IsVisibleInDynamoLibrary(false)]
        public static IEnumerable<Symbol> GetAllSymbols()
        {
            return ConvertForgeSymbolDictionaryToCollection(ForgeUnitsEngine.getAllSymbols());
        }
        internal static IEnumerable<Quantity> CovertForgeQuantityDictionaryToCollection(Dictionary<string, Quantity> forgeDictionary)
        {
            List<Quantity> list = new List<Quantity>();
            Dictionary<string, Version> allRegisteredQuantityVersions = GetAllRegisteredQuantityVersions(forgeDictionary);
            foreach (KeyValuePair<string, Version> item in allRegisteredQuantityVersions) {
                string key = item.Key + "-" + item.Value.ToString();
                if (forgeDictionary.TryGetValue(key, out Quantity value))
                    list.Add(new Quantity(value));
            }
            return list;
        }
        internal static IEnumerable<Symbol> ConvertForgeSymbolDictionaryToCollection(Dictionary<string, Symbol> forgeDictionary)
        {
            List<Symbol> list = new List<Symbol>();
            Dictionary<string, Version> allLastestRegisteredSymbolVersions = GetAllLastestRegisteredSymbolVersions(forgeDictionary);
            foreach (KeyValuePair<string, Version> item in allLastestRegisteredSymbolVersions) {
                string key = item.Key + "-" + item.Value.ToString();
                if (forgeDictionary.TryGetValue(key, out Symbol value))
                    list.Add(new Symbol(value));
            }
            return list;
        }
        internal static IEnumerable<Unit> ConvertForgeUnitDictionaryToCollection(Dictionary<string, Unit> forgeDictionary)
        {
            List<Unit> list = new List<Unit>();
            Dictionary<string, Version> allLatestRegisteredUnitVersions = GetAllLatestRegisteredUnitVersions(forgeDictionary);
            foreach (KeyValuePair<string, Version> item in allLatestRegisteredUnitVersions) {
                string key = item.Key + "-" + item.Value.ToString();
                if (forgeDictionary.TryGetValue(key, out Unit value))
                    list.Add(new Unit(value));
            }
            return list;
        }
        internal static Dictionary<string, Version> GetAllRegisteredQuantityVersions()
        {
            return GetAllRegisteredQuantityVersions(ForgeUnitsEngine.getAllQuantities());
        }
        internal static Dictionary<string, Version> GetAllRegisteredQuantityVersions(Dictionary<string, Quantity> forgeDictionary)
        {
            Dictionary<string, Version> dictionary = new Dictionary<string, Version>();
            foreach (string key in forgeDictionary.Keys) {
                if (TryParseTypeId(key, out string typeName, out Version version) && (!dictionary.TryGetValue(typeName, out Version value) || value.CompareTo(version) < 0))
                    dictionary[typeName] = version;
            }
            return dictionary;
        }
        internal static Dictionary<string, Version> GetAllLastestRegisteredSymbolVersions()
        {
            return GetAllLastestRegisteredSymbolVersions(ForgeUnitsEngine.getAllSymbols());
        }
        internal static Dictionary<string, Version> GetAllLastestRegisteredSymbolVersions(Dictionary<string, Symbol> forgeDictionary)
        {
            Dictionary<string, Version> dictionary = new Dictionary<string, Version>();
            foreach (string key in forgeDictionary.Keys) {
                if (TryParseTypeId(key, out string typeName, out Version version) && (!dictionary.TryGetValue(typeName, out Version value) || value.CompareTo(version) < 0))
                    dictionary[typeName] = version;
            }
            return dictionary;
        }
        internal static Dictionary<string, Version> GetAllLatestRegisteredUnitVersions()
        {
            return GetAllLatestRegisteredUnitVersions(ForgeUnitsEngine.getAllUnits());
        }
        internal static Dictionary<string, Version> GetAllLatestRegisteredUnitVersions(Dictionary<string, Unit> forgeDictionary)
        {
            Dictionary<string, Version> dictionary = new Dictionary<string, Version>();
            foreach (string key in forgeDictionary.Keys) {
                if (TryParseTypeId(key, out string typeName, out Version version) && (!dictionary.TryGetValue(typeName, out Version value) || value.CompareTo(version) < 0))
                    dictionary[typeName] = version;
            }
            return dictionary;
        }
        internal static bool TryParseTypeId(string typeId, out string typeName, out Version version)
        {
            string[] array = typeId.Split('-', StringSplitOptions.None);
            if (array.Length == 2 && Version.TryParse(array[1], out Version result)) {
                typeName = array[0];
                version = result;
                return true;
            }
            typeName = "";
            version = null;
            return false;
        }
    }
}