using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace WingServerCommon.Config.Parameters
{
public class ParameterSerializer
{
///
/// Deserialize json file to parameter
///
/// File path that will be deserialize
/// Parameter list.
public static IEnumerable Deserialize(string filePath)
{
var content = File.ReadAllText(filePath);
var configCrypter = new ConfigCrypter();
content = configCrypter.DecryptDES(content);
var childrenList = JToken.Parse(content).Children();
var parameters = new List();
foreach (var child in childrenList)
{
var setionParameters = ParseTokenSetions(child);
parameters.AddRange(setionParameters);
}
return parameters;
}
private static IEnumerable ParseTokenSetions(JToken children)
{
var item = (JProperty)children;
var parsedParameters = ParseToken(item.Name, item.Value.Children()).ToList();
return parsedParameters;
}
private static IEnumerable ParseToken(string sectionName, JEnumerable childrenList)
{
var parameters = new List();
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;
parameters.Add(parameter);
continue;
}
if (IsEnumParameter(jObject))
{
var parameter = ParseEnumParameter(item.Name, jObject);
parameter.Section = sectionName;
parameters.Add(parameter);
continue;
}
var parsedParameters = ParseToken(sectionName, jObject.Children()).ToList();
parameters.AddRange(parsedParameters);
}
if (item.Value is JValue jValue)
{
var parameter = ParseBasicParameter(jValue, item.Name);
parameter.Section = sectionName;
parameters.Add(parameter);
}
}
return parameters;
}
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}");
}
}
}