using System.Collections.Concurrent;
using Newtonsoft.Json.Linq;
namespace WingServerCommon.Config.Parameters
{
public class ParameterDictionarySerializer
{
///
/// Deserialize json file to parameter
///
/// File path or json string that will be deserialize
/// str type, 0-file Path, 1-json string
/// Parameter list.
public static ConcurrentDictionary Deserialize(string str, int type = 0)
{
var content = "";
if (type == 0)
{
content = File.ReadAllText(str);
}
else
{
content = str;
}
//Decrypt text
var configCrypter = new ConfigCrypter();
content = configCrypter.DecryptDES(content);
var childrenList = JToken.Parse(content).Children();
var parameters = new ConcurrentDictionary();
foreach (var child in childrenList)
{
ParseTokenSetions(child, ref parameters);
}
return parameters;
}
private static void ParseTokenSetions(JToken children, ref ConcurrentDictionary dic)
{
var item = (JProperty)children;
ParseToken(item.Name, item.Value.Children(), ref dic);
}
private static void ParseToken(string sectionName, JEnumerable childrenList, ref ConcurrentDictionary parameters)
{
foreach (var jToken in childrenList)
{
var item = (JProperty)jToken;
if (item.Value is JArray jArray)
{
//TODO Do we have array parameter?
continue;
}
if (item.Value is JObject jObject)
{
if (IsRangeParameter(jObject))
{
var parameter = ParseRangeParameter(jObject, item.Name);
parameter.Section = sectionName;
var rangeKey = parameter.Section + "_" + parameter.Name;
parameters.TryAdd(rangeKey, parameter);
continue;
}
if (IsEnumParameter(jObject))
{
var parameter = ParseEnumParameter(item.Name, jObject);
parameter.Section = sectionName;
var enumKey = parameter.Section + "_" + parameter.Name;
parameters.TryAdd(enumKey, parameter);
continue;
}
ParseToken(sectionName, jObject.Children(), ref parameters);
}
if (item.Value is JValue jValue)
{
var parameter = ParseBasicParameter(jValue, item.Name);
parameter.Section = sectionName;
var valueKey = parameter.Section + "_" + parameter.Name;
parameters.TryAdd(valueKey, parameter);
}
}
}
private static bool IsEnumParameter(JObject jObject)
{
return jObject.Children().Any(m => ((JProperty)m).Name == "Source");
}
private static bool IsRangeParameter(JObject jObject)
{
return jObject.Children().Any(m => ((JProperty)m).Name == "MaxValue");
}
private static IParameter ParseEnumParameter(string name, JObject jObject)
{
var defaultValue = jObject["DefaultValue"]?.Value();
switch (defaultValue?.Type)
{
case JTokenType.String:
return new EnumStringParameter
{
Name = name,
Source = jObject["Source"].Values().ToList(),
Value = defaultValue.Value()
};
//TODO other types
}
throw new ArgumentException($"Invalid enum parameter {name}.");
}
private static IParameter ParseRangeParameter(JObject jObject, string key)
{
var max = jObject["MaxValue"].Value();
switch (max.Type)
{
case JTokenType.Integer:
{
if (max.Value() > int.MaxValue)
{
var defaultValue = jObject["DefaultValue"].Value();
var minValue = jObject["MinValue"].Value();
var maxValue = max.Value();
var longRangeValue = new RangeLongParameter
{
Name = key,
Value = defaultValue,
MaxValue = maxValue,
MinValue = minValue
};
}
else
{
var defaultValue = jObject["DefaultValue"].Value();
var minValue = jObject["MinValue"].Value();
var maxValue = max.Value();
var intRangeValue = new RangeIntParameter
{
Name = key,
Value = defaultValue,
MaxValue = maxValue,
MinValue = minValue
};
}
break;
}
}
throw new ArgumentException($"Invalid range parameter with name {key}.");
}
private static IParameter ParseBasicParameter(JValue jValue, string key)
{
if (jValue.Type == JTokenType.Integer)
{
return new IntParameter { Name = key, Value = jValue.Value() };
}
if (jValue.Type == JTokenType.Boolean)
{
return new BoolParameter { Name = key, Value = jValue.Value() };
}
if (jValue.Type == JTokenType.String)
{
return new StringParameter { Name = key, Value = jValue.Value() };
}
//TODO Implement FloatParameter
//if (jValue.Type == JTokenType.Float)
//{
// return new FloatParameter { Name = key, Value = jValue.Value() };
//}
throw new ArgumentException($"Invalid jValue type {jValue.Type}");
}
}
}