using System.Collections; using LibCameraSharp; namespace GSS2.Core.Helpers; public static class ControlValueHelper { private static readonly Dictionary> _valueParsers = new() { { typeof(bool ), (obj, _) => ParseValue(obj, bool .TryParse) }, { typeof(byte ), (obj, _) => ParseValue(obj, byte .TryParse) }, { typeof(float ), (obj, _) => ParseValue(obj, float .TryParse) }, { typeof(long ), (obj, _) => ParseValue(obj, long .TryParse) }, { typeof(ushort ), (obj, _) => ParseValue(obj, ushort.TryParse) }, { typeof(uint ), (obj, _) => ParseValue(obj, uint .TryParse) }, { typeof(int ), ParseValueInt }, // int - особый случай потому что он может использовать ControlId.Enumerators для прообразования стокового "enum" в значение { typeof(Rectangle), ParseValueRectangle }, { typeof(Size ), ParseValueSize }, { typeof(Point ), ParseValuePoint } }; private delegate bool ParseValueDelegate(string s, out T value); private static object? ParseValue(object obj, ParseValueDelegate parser) where T : struct { if (obj is T value) return value; if (obj is string str && parser(str, out var parsed)) return parsed; return null; } private static object? ParseValueInt(object obj, ControlId id) { if (obj is int value) return value; if (obj is string str) { if (int.TryParse(str, out value)) return value; var match = id.Enumerators.FirstOrDefault(e => e.Value == str); if (!match.Equals(default(KeyValuePair))) return match.Key; } return null; } private static object? ParseValueRectangle(object obj, ControlId id) { if (obj is Rectangle value) return value; if (obj is IEnumerable enumerable) { var list = enumerable.Cast(); if (list.Count() != 4) return null; if (!int.TryParse(list.Skip(0).First(), out var x)) return null; if (!int.TryParse(list.Skip(1).First(), out var y)) return null; if (!uint.TryParse(list.Skip(2).First(), out var width)) return null; if (!uint.TryParse(list.Skip(3).First(), out var height)) return null; return new Rectangle(x, y, width, height); } return null; } private static object? ParseValueSize(object obj, ControlId id) { if (obj is Size value) return value; if (obj is IEnumerable enumerable) { var list = enumerable.Cast(); if (list.Count() != 2) return null; if (!uint.TryParse(list.Skip(0).First(), out var width)) return null; if (!uint.TryParse(list.Skip(1).First(), out var height)) return null; return new Size(width, height); } return null; } private static object? ParseValuePoint(object obj, ControlId id) { if (obj is Point value) return value; if (obj is IEnumerable enumerable) { var list = enumerable.Cast(); if (list.Count() != 4) return null; if (!int.TryParse(list.Skip(0).First(), out var x)) return null; if (!int.TryParse(list.Skip(1).First(), out var y)) return null; return new Point(x, y); } return null; } private static T? ConvertValueStruct(object obj, ControlId id) where T : struct { var type = typeof(T); if (!_valueParsers.ContainsKey(type)) return null; var parsed = _valueParsers[type](obj, id); var result = (T?)parsed; return result; } private static T? ConvertValueClass(object obj, ControlId id) where T : class { var type = typeof(T); if (!_valueParsers.ContainsKey(type)) return null; var parsed = _valueParsers[type](obj, id); var result = (T?)parsed; return result; } private static readonly Dictionary> _controlValueConverters = new() { { ControlTypeEnum.Bool , (obj, id) => { var v = ConvertValueStruct(obj, id); return v is null ? null : new ControlValueBool (v.Value); } }, { ControlTypeEnum.Byte , (obj, id) => { var v = ConvertValueStruct(obj, id); return v is null ? null : new ControlValueByte (v.Value); } }, { ControlTypeEnum.Float , (obj, id) => { var v = ConvertValueStruct(obj, id); return v is null ? null : new ControlValueFloat (v.Value); } }, { ControlTypeEnum.Integer32 , (obj, id) => { var v = ConvertValueStruct(obj, id); return v is null ? null : new ControlValueInteger32 (v.Value); } }, { ControlTypeEnum.Integer64 , (obj, id) => { var v = ConvertValueStruct(obj, id); return v is null ? null : new ControlValueInteger64 (v.Value); } }, { ControlTypeEnum.Unsigned16, (obj, id) => { var v = ConvertValueStruct(obj, id); return v is null ? null : new ControlValueUnsigned16(v.Value); } }, { ControlTypeEnum.Unsigned32, (obj, id) => { var v = ConvertValueStruct(obj, id); return v is null ? null : new ControlValueUnsigned32(v.Value); } }, { ControlTypeEnum.Rectangle , (obj, id) => { var v = ConvertValueClass (obj, id); return v is null ? null : new ControlValueRectangle (v); } }, { ControlTypeEnum.Size , (obj, id) => { var v = ConvertValueClass (obj, id); return v is null ? null : new ControlValueSize (v); } }, { ControlTypeEnum.Point , (obj, id) => { var v = ConvertValueClass (obj, id); return v is null ? null : new ControlValuePoint (v); } } }; private static readonly Dictionary> _controlValueClapers = new() { { ControlTypeEnum.Bool , (value, id, info) => { } }, { ControlTypeEnum.Byte , (value, id, info) => { if (value is ControlValueByte typed && info.Min is ControlValueByte typedMin && info.Max is ControlValueByte typedMax) typed.Set(Math.Clamp(typed.Get(), typedMin.Get(), typedMax.Get())); } }, { ControlTypeEnum.Float , (value, id, info) => { if (value is ControlValueFloat typed && info.Min is ControlValueFloat typedMin && info.Max is ControlValueFloat typedMax) typed.Set(Math.Clamp(typed.Get(), typedMin.Get(), typedMax.Get())); } }, { ControlTypeEnum.Integer32 , (value, id, info) => { if (value is ControlValueInteger32 typed && info.Min is ControlValueInteger32 typedMin && info.Max is ControlValueInteger32 typedMax) typed.Set(Math.Clamp(typed.Get(), typedMin.Get(), typedMax.Get())); } }, { ControlTypeEnum.Integer64 , (value, id, info) => { if (value is ControlValueInteger64 typed && info.Min is ControlValueInteger64 typedMin && info.Max is ControlValueInteger64 typedMax) typed.Set(Math.Clamp(typed.Get(), typedMin.Get(), typedMax.Get())); } }, { ControlTypeEnum.Unsigned16, (value, id, info) => { if (value is ControlValueUnsigned16 typed && info.Min is ControlValueUnsigned16 typedMin && info.Max is ControlValueUnsigned16 typedMax) typed.Set(Math.Clamp(typed.Get(), typedMin.Get(), typedMax.Get())); } }, { ControlTypeEnum.Unsigned32, (value, id, info) => { if (value is ControlValueUnsigned32 typed && info.Min is ControlValueUnsigned32 typedMin && info.Max is ControlValueUnsigned32 typedMax) typed.Set(Math.Clamp(typed.Get(), typedMin.Get(), typedMax.Get())); } } }; public static ControlValue? ConvertToControlValue(object obj, ControlId id, ControlInfo info) { if (!_controlValueConverters.TryGetValue(id.Type, out var converter)) return null; var controlValue = converter(obj, id); if (controlValue is null) return null; if (!_controlValueClapers.TryGetValue(id.Type, out var clamper)) return controlValue; clamper(controlValue, id, info); return controlValue; } private static readonly Dictionary> _arrayParsers = new() { { typeof(bool ), ParseArray }, { typeof(byte ), ParseArray }, { typeof(float ), ParseArray }, { typeof(long ), ParseArray }, { typeof(ushort ), ParseArray }, { typeof(uint ), ParseArray }, { typeof(int ), ParseArray }, { typeof(Rectangle), ParseArray}, { typeof(Size ), ParseArray }, { typeof(Point ), ParseArray } }; private static object? ParseArray(object obj, ControlId id) { if (obj is not IEnumerable enumerable) return null; var list = enumerable.Cast().ToList(); if ((ulong)list.Count != id.Size) return null; var array = new T[list.Count]; for (int i = 0; i < list.Count; i++) { var parsed = _valueParsers[typeof(T)](list[i], id); if (parsed is null) return null; array[i] = (T)parsed; } return array; } private static IEnumerable? ConvertArray(object obj, ControlId id) { var type = typeof(T); if (!_arrayParsers.ContainsKey(type)) return null; var parsed = _arrayParsers[type](obj, id); var result = (T[]?)parsed; return result; } private static readonly Dictionary> _controlArrayConverters = new() { { ControlTypeEnum.Bool , (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueBoolSpan (v); } }, { ControlTypeEnum.Byte , (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueByteSpan (v); } }, { ControlTypeEnum.Float , (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueFloatSpan (v); } }, { ControlTypeEnum.Integer32 , (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueInteger32Span (v); } }, { ControlTypeEnum.Integer64 , (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueInteger64Span (v); } }, { ControlTypeEnum.Unsigned16, (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueUnsigned16Span(v); } }, { ControlTypeEnum.Unsigned32, (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueUnsigned32Span(v); } }, { ControlTypeEnum.Rectangle , (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueRectangleSpan (v); } }, { ControlTypeEnum.Size , (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValueSizeSpan (v); } }, { ControlTypeEnum.Point , (obj, id) => { var v = ConvertArray(obj, id); return v is null ? null : new ControlValuePointSpan (v); } } }; private static readonly Dictionary> _controlArrayClapers = new() { { ControlTypeEnum.Bool , (value, id, info) => { } }, { ControlTypeEnum.Byte , (value, id, info) => { if (value is ControlValueByteSpan typed && info.Min is ControlValueByte typedMin && info.Max is ControlValueByte typedMax) typed.Set(typed.Get().Select(v => Math.Clamp(v, typedMin.Get(), typedMax.Get()))); } }, { ControlTypeEnum.Float , (value, id, info) => { if (value is ControlValueFloatSpan typed && info.Min is ControlValueFloat typedMin && info.Max is ControlValueFloat typedMax) typed.Set(typed.Get().Select(v => Math.Clamp(v, typedMin.Get(), typedMax.Get()))); } }, { ControlTypeEnum.Integer32 , (value, id, info) => { if (value is ControlValueInteger32Span typed && info.Min is ControlValueInteger32 typedMin && info.Max is ControlValueInteger32 typedMax) typed.Set(typed.Get().Select(v => Math.Clamp(v, typedMin.Get(), typedMax.Get()))); } }, { ControlTypeEnum.Integer64 , (value, id, info) => { if (value is ControlValueInteger64Span typed && info.Min is ControlValueInteger64 typedMin && info.Max is ControlValueInteger64 typedMax) typed.Set(typed.Get().Select(v => Math.Clamp(v, typedMin.Get(), typedMax.Get()))); } }, { ControlTypeEnum.Unsigned16, (value, id, info) => { if (value is ControlValueUnsigned16Span typed && info.Min is ControlValueUnsigned16 typedMin && info.Max is ControlValueUnsigned16 typedMax) typed.Set(typed.Get().Select(v => Math.Clamp(v, typedMin.Get(), typedMax.Get()))); } }, { ControlTypeEnum.Unsigned32, (value, id, info) => { if (value is ControlValueUnsigned32Span typed && info.Min is ControlValueUnsigned32 typedMin && info.Max is ControlValueUnsigned32 typedMax) typed.Set(typed.Get().Select(v => Math.Clamp(v, typedMin.Get(), typedMax.Get()))); } }, { ControlTypeEnum.Rectangle , (value, id, info) => { if (value is ControlValueRectangleSpan typed && info.Min is ControlValueRectangle typedMin && info.Max is ControlValueRectangle typedMax) typed.Set(typed.Get().Select(v => new Rectangle(Math.Clamp(v.X, typedMin.Get().X, typedMax.Get().X ), Math.Clamp(v.Y, typedMin.Get().Y, typedMax.Get().Y ), Math.Clamp(v.Width, typedMin.Get().Width, typedMax.Get().Width ), Math.Clamp(v.Height, typedMin.Get().Height, typedMax.Get().Height)))); } }, { ControlTypeEnum.Size , (value, id, info) => { if (value is ControlValueSizeSpan typed && info.Min is ControlValueSize typedMin && info.Max is ControlValueSize typedMax) typed.Set(typed.Get().Select(v => new Size( Math.Clamp(v.Width, typedMin.Get().Width, typedMax.Get().Width ), Math.Clamp(v.Height, typedMin.Get().Height, typedMax.Get().Height)))); } }, { ControlTypeEnum.Point , (value, id, info) => { if (value is ControlValuePointSpan typed && info.Min is ControlValuePoint typedMin && info.Max is ControlValuePoint typedMax) typed.Set(typed.Get().Select(v => new Point( Math.Clamp(v.X, typedMin.Get().X, typedMax.Get().X ), Math.Clamp(v.Y, typedMin.Get().Y, typedMax.Get().Y )))); } }, }; public static ControlValue? ConvertToControlArray(object obj, ControlId id, ControlInfo info) { if (!_controlArrayConverters.ContainsKey(id.Type)) return null; var controlValue = _controlArrayConverters[id.Type](obj, id); if (controlValue is null) return null; if (!_controlArrayClapers.TryGetValue(id.Type, out var clamper)) return controlValue; clamper(controlValue, id, info); return controlValue; } }