Symbol
A text symbol used to associate a value with a Unit system.
            
using Autodesk.ForgeUnits;
using System;
using System.Collections.Generic;
using System.Text;
namespace DynamoUnits
{
    public class Symbol
    {
        internal readonly Symbol forgeSymbol;
        internal readonly PrefixOrSuffix forgePrefixOrSuffix;
        public string TypeId => forgeSymbol.getTypeId();
        public Unit Unit => new Unit(forgeSymbol.getUnit());
        public string Text {
            get {
                if (forgePrefixOrSuffix == null)
                    return "";
                return Encoding.UTF8.GetString(Encoding.Default.GetBytes(forgePrefixOrSuffix.getText()));
            }
        }
        public bool Space {
            get {
                if (forgePrefixOrSuffix != null)
                    return forgePrefixOrSuffix.hasSpace();
                return true;
            }
        }
        internal Symbol(Symbol symbol)
        {
            if (symbol == null)
                throw new ArgumentNullException();
            forgeSymbol = symbol;
            forgePrefixOrSuffix = symbol.getPrefixOrSuffix();
        }
        public static Symbol ByTypeID(string typeId)
        {
            try {
                return new Symbol(Utilities.ForgeUnitsEngine.getSymbol(typeId));
            } catch (Exception) {
                if (Utilities.TryParseTypeId(typeId, out string typeName, out Version _)) {
                    Dictionary<string, Version> allLastestRegisteredSymbolVersions = Utilities.GetAllLastestRegisteredSymbolVersions();
                    if (allLastestRegisteredSymbolVersions.TryGetValue(typeName, out Version value))
                        return new Symbol(Utilities.ForgeUnitsEngine.getSymbol(typeName + "-" + value.ToString()));
                }
                throw;
            }
        }
        public static IEnumerable<Symbol> SymbolsByUnit(Unit unit)
        {
            Dictionary<string, Symbol> symbols = Utilities.ForgeUnitsEngine.getSymbols(unit.TypeId);
            return Utilities.ConvertForgeSymbolDictionaryToCollection(symbols);
        }
        public static string StringifyDecimal(double value, int precision, Symbol symbol, bool removeTrailingZeros = false)
        {
            return Encoding.UTF8.GetString(Encoding.Default.GetBytes(Utilities.ForgeUnitsEngine.stringifyFixedPoint(value, (byte)precision, symbol.TypeId, removeTrailingZeros)));
        }
        public static string StringifyFraction(double value, int precision, Symbol symbol)
        {
            return Encoding.UTF8.GetString(Encoding.Default.GetBytes(Utilities.ForgeUnitsEngine.stringifyFraction(value, (byte)precision, symbol.TypeId)));
        }
        public override string ToString()
        {
            if (!(Text != ""))
                return "Symbol";
            return "Symbol(Text = " + Text + ")";
        }
        public override int GetHashCode()
        {
            return (Text ?? string.Empty).GetHashCode() ^ (TypeId ?? string.Empty).GetHashCode();
        }
        public override bool Equals(object obj)
        {
            return EqualsImpl(obj as Symbol);
        }
        internal bool EqualsImpl(Symbol u)
        {
            if ((object)u == null)
                return false;
            if ((object)this == u)
                return true;
            if (GetType() != u.GetType())
                return false;
            if (Text == u.Text)
                return TypeId == u.TypeId;
            return false;
        }
        public static bool operator ==(Symbol lhs, Symbol rhs)
        {
            if ((object)lhs == null) {
                if ((object)rhs == null)
                    return true;
                return false;
            }
            return lhs.EqualsImpl(rhs);
        }
        public static bool operator !=(Symbol lhs, Symbol rhs)
        {
            return !(lhs == rhs);
        }
    }
}