using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace SickBlazorApp.Services
{
    public class EdsParser
    {
        private readonly Dictionary<string, Dictionary<string, string>> _sections = new();

        public EdsParser(string edsPath)
        {
            LoadEds(edsPath);
        }

        private void LoadEds(string edsPath)
        {
            // Đọc embed resource
            var assembly = Assembly.GetExecutingAssembly();
            using var stream = assembly.GetManifestResourceStream(edsPath);
            if (stream == null) throw new FileNotFoundException("EDS not found: " + edsPath);

            using var reader = new StreamReader(stream);
            string? line;
            string currentSection = string.Empty;
            var currentSub = new Dictionary<string, string>();

            while ((line = reader.ReadLine()) != null)
            {
                line = line.Trim();
                if (string.IsNullOrEmpty(line) || line.StartsWith(";")) continue;

                if (line.StartsWith("[") && line.EndsWith("]"))
                {
                    if (!string.IsNullOrEmpty(currentSection))
                    {
                        _sections[currentSection] = currentSub;
                    }
                    currentSection = line[1..^1].ToLower();  // e.g. "1000" hoặc "1800sub1"
                    currentSub = new Dictionary<string, string>();
                }
                else if (line.Contains("="))
                {
                    var parts = line.Split('=', 2);
                    var key = parts[0].Trim().ToLower();
                    var value = parts[1].Trim();
                    currentSub[key] = value;
                }
            }
            if (!string.IsNullOrEmpty(currentSection))
            {
                _sections[currentSection] = currentSub;
            }
        }

        // Helper lấy giá trị
        public string GetValue(string section, string key)
        {
            section = section.ToLower();
            if (_sections.TryGetValue(section, out var sub) && sub.TryGetValue(key.ToLower(), out var value))
            {
                return value;
            }
            return string.Empty;
        }

        // Ví dụ lấy TPDO1 COB-ID base (trả $nodeid + 0x180 → parse 0x180)
        public uint GetTpdo1BaseCobId()
        {
            var cob = GetValue("1800sub1", "defaultvalue");  // "$NodeID + 0x180"
            var hexPart = cob.Split('+')[1].Trim();  // "0x180"
            return Convert.ToUInt32(hexPart, 16);  // 384 (0x180)
        }

        // Lấy access-code (EDS không default, nhưng manual 0x98127634 → hard-code tạm hoặc thêm param)
        public uint GetAccessCode()
        {
            // EDS không có default cho 0x2009sub1 → dùng từ manual
            return 0x98127634;  // Cập nhật từ EDS/manual
        }

        // Tính scale (mm per count)
        public double GetPositionScale()
        {
            // Lấy resolution per revolution từ EDS (0x6001 default = 0x4000 = 16384 counts/rev)
            var resPerRevHex = GetValue("6001", "defaultvalue") ?? "0x4000";
            var countsPerRev = Convert.ToUInt32(resPerRevHex, 16);  // 16384

            // Thông số dây kéo BCG08: 230 mm per revolution (từ datasheet SICK BCG08 series)
            const double mmPerRev = 230.0;  // chuẩn từ datasheet wire draw

            // Scale = mm per count = mm/rev / counts/rev
            double scale = mmPerRev / countsPerRev;

            // Kết quả ≈ 230 / 16384 ≈ 0.014038 mm/count
            return scale;
        }

        // Lấy baudrate map (index → bitrate)
        public Dictionary<byte, int> GetBaudrateMap()
        {
            var map = new Dictionary<byte, int>();
            byte index = 0;
            if (GetValue("deviceinfo", "baudrate_1000") == "1") map[index++] = 1000000;
            if (GetValue("deviceinfo", "baudrate_800") == "1") map[index++] = 800000;
            if (GetValue("deviceinfo", "baudrate_500") == "1") map[index++] = 500000;
            if (GetValue("deviceinfo", "baudrate_250") == "1") map[index++] = 250000;
            if (GetValue("deviceinfo", "baudrate_125") == "1") map[index++] = 125000;
            if (GetValue("deviceinfo", "baudrate_100") == "1") map[index++] = 100000;
            if (GetValue("deviceinfo", "baudrate_50") == "1") map[index++] = 50000;
            if (GetValue("deviceinfo", "baudrate_20") == "1") map[index++] = 20000;
            if (GetValue("deviceinfo", "baudrate_10") == "1") map[index++] = 10000;
            return map;
        }

        // Kiểm tra position mapping (byte 0-3 uint32?)
        public bool IsPositionMappedToTpdo1()
        {
            var mapping = GetValue("1a00sub1", "defaultvalue");  // 0x60040020
            return mapping == "0x60040020";  // Position 32-bit
        }
    }
}
