using Permission;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PlcUiControl
{
    internal static class CommonLib
    {

        public static void ApplyPermissionState(IPermissionControl permissionControl, IPlcUiControl uiControl, Control winFormControl)
        {
            if (permissionControl.IsPermissionGot)
            {
                winFormControl.Enabled = true;

                if (uiControl.InvisibilityTriggerNode != null)
                {
                    winFormControl.Visible = !uiControl.Invisibility;
                }

                if (winFormControl.Visible)
                {
                    if (uiControl.DisabilityTriggerNode != null)
                    {
                        winFormControl.Enabled = !uiControl.Disability;
                    }
                    else
                    {
                        winFormControl.Enabled = true;
                    }
                }
            }
            else
            {
                winFormControl.Enabled = false;
            }
        }

        public static object Convert2NodeTypeObject(NodeType nodeType, object value)
        {
            if (value == null)
                return null;

            object obj = null;

            switch (nodeType)
            {
                case NodeType.BOOL:
                    {
                        if (value is bool b)
                        {
                            obj = b;
                        }
                        else if (value is string s)
                        {
                            obj = bool.TryParse(s, out b) ? b : false;
                        }
                        else
                        {
                            int.TryParse(value.ToString(), out int i);
                            obj = i != 0;
                        }
                    }
                    break;

                case NodeType.BYTE:
                    {
                        if (value is byte bt)
                            obj = bt;
                        else if (value is string s && byte.TryParse(s, out byte sb))
                            obj = sb;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (byte)(l & 0xFF); // 截断高位
                        else
                            obj = (byte)0;
                    }
                    break;

                case NodeType.WORD:
                    {
                        if (value is ushort w)
                            obj = w;
                        else if (value is string s && ushort.TryParse(s, out ushort sw))
                            obj = sw;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (ushort)(l & 0xFFFF); // 截断高位
                        else
                            obj = (ushort)0;
                    }
                    break;

                case NodeType.DWORD:
                    {
                        if (value is uint dw)
                            obj = dw;
                        else if (value is string s && uint.TryParse(s, out uint sdw))
                            obj = sdw;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (uint)(l & 0xFFFFFFFF); // 截断高位
                        else
                            obj = (uint)0;
                    }
                    break;

                case NodeType.LWORD:
                    {
                        if (value is ulong lwd)
                            obj = lwd;
                        else if (value is string s && ulong.TryParse(s, out ulong slwd))
                            obj = slwd;
                        else if (decimal.TryParse(value.ToString(), out decimal m))
                            obj = (ulong)(decimal.ToUInt64(m));
                        else
                            obj = (ulong)0;
                    }
                    break;

                case NodeType.SINT:
                    {
                        if (value is sbyte sb)
                            obj = sb;
                        else if (value is string s && sbyte.TryParse(s, out sbyte sbs))
                            obj = sbs;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (sbyte)(l & 0xFF);
                        else
                            obj = (sbyte)0;
                    }
                    break;

                case NodeType.USINT:
                    {
                        if (value is byte usb)
                            obj = usb;
                        else if (value is string s && byte.TryParse(s, out byte usbs))
                            obj = usbs;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (byte)(l & 0xFF);
                        else
                            obj = (byte)0;
                    }
                    break;

                case NodeType.INT:
                    {
                        if (value is short i16)
                            obj = i16;
                        else if (value is string s && short.TryParse(s, out short si16))
                            obj = si16;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (short)(l & 0xFFFF);
                        else
                            obj = (short)0;
                    }
                    break;

                case NodeType.UINT:
                    {
                        if (value is ushort ui16)
                            obj = ui16;
                        else if (value is string s && ushort.TryParse(s, out ushort sui16))
                            obj = sui16;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (ushort)(l & 0xFFFF);
                        else
                            obj = (ushort)0;
                    }
                    break;

                case NodeType.DINT:
                    {
                        if (value is int i32)
                            obj = i32;
                        else if (value is string s && int.TryParse(s, out int si32))
                            obj = si32;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (int)(l & 0xFFFFFFFF);
                        else
                            obj = 0;
                    }
                    break;

                case NodeType.UDINT:
                    {
                        if (value is uint ui32)
                            obj = ui32;
                        else if (value is string s && uint.TryParse(s, out uint sui32))
                            obj = sui32;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (uint)(l & 0xFFFFFFFF);
                        else
                            obj = (uint)0;
                    }
                    break;

                case NodeType.LINT:
                    {
                        if (value is long i64)
                            obj = i64;
                        else if (value is string s && long.TryParse(s, out long si64))
                            obj = si64;
                        else if (decimal.TryParse(value.ToString(), out decimal m))
                            obj = decimal.ToInt64(m);
                        else
                            obj = 0L;
                    }
                    break;

                case NodeType.ULINT:
                    {
                        if (value is ulong ui64)
                            obj = ui64;
                        else if (value is string s && ulong.TryParse(s, out ulong sui64))
                            obj = sui64;
                        else if (decimal.TryParse(value.ToString(), out decimal m))
                            obj = decimal.ToUInt64(m);
                        else
                            obj = 0UL;
                    }
                    break;

                case NodeType.REAL:
                    {
                        if (value is float f32)
                            obj = f32;
                        else if (value is string s && float.TryParse(s, out float sf32))
                            obj = sf32;
                        else if (double.TryParse(value.ToString(), out double d))
                            obj = (float)d;
                        else
                            obj = 0.0f;
                    }
                    break;

                case NodeType.LREAL:
                    {
                        if (value is double f64)
                            obj = f64;
                        else if (value is string s && double.TryParse(s, out double sf64))
                            obj = sf64;
                        else if (double.TryParse(value.ToString(), out double d))
                            obj = d;
                        else
                            obj = 0.0;
                    }
                    break;

                case NodeType.STRING:
                    {
                        if (value is string str)
                        {
                            obj = str;
                        }
                        else
                        {
                            obj = value.ToString() ?? "";
                        }
                    }
                    break;

                case NodeType.TIME:
                    {
                        if (value is ushort ui16)
                            obj = ui16;
                        else if (value is string s && ushort.TryParse(s, out ushort sui16))
                            obj = sui16;
                        else if (long.TryParse(value.ToString(), out long l))
                            obj = (ushort)(l & 0xFFFF);
                        else
                            obj = (ushort)0;
                    }
                    break;
                default:
                    throw new ArgumentOutOfRangeException(nameof(value), value, null);
            }
            return obj;
        }

        public static string FormatNumber(double value, int integerDigits, int decimalDigits,double gain,out double result)
        {
            if(integerDigits<1)
                return FormatNumber(value,decimalDigits,gain,out result);

            // 四舍五入
            value *= gain;
            decimal rounded = Math.Round((decimal)value, decimalDigits);

            // 构造格式字符串
            string integerFormat = new string('0', integerDigits); // 如 "00000"
            string decimalFormat = decimalDigits > 0 ? "." + new string('0', decimalDigits) : ""; // 如 ".00"
            string format = integerFormat + decimalFormat; // 如 "00000.00"

            string rt = ((double)rounded).ToString(format);
            result = Convert.ToDouble(rt);
            // 格式化
            return rt;
        }
        public static string FormatNumber(double value, int decimalDigits, double gain,out double result)
        {
            // 四舍五入
            value *= gain;
            decimal rounded = Math.Round((decimal)value, decimalDigits);
            result = (double)rounded;
            if (decimalDigits < 0)
                decimalDigits = 0;
            // 格式化
            return ((double)rounded).ToString($"f{decimalDigits}");
        }
    }
    public static class StringExtensions
    {
        public static string AfterLast(this string source, char separator)
        {
            if (string.IsNullOrEmpty(source)) return source;
            int index = source.LastIndexOf(separator);
            return index >= 0 && index < source.Length - 1
                ? source.Substring(index + 1)
                : "";
        }
    }
}
