using System.Collections;
using System.Net;
using DotNext;
using Newtonsoft.Json;
using server.Services;
using WebProtocol;

namespace Peripherals.JtagClient;

/// <summary>
/// Global Constant Jtag Address
/// </summary>
public static class JtagAddr
{
    /// <summary>
    /// Jtag State Reg
    /// </summary>
    public const UInt32 STATE = 0x10_00_00_00;
    /// <summary>
    /// Jtag Read Reg
    /// </summary>
    public const UInt32 READ_DATA = 0x10_00_00_01;
    /// <summary>
    /// Jtag Write Reg
    /// </summary>
    public const UInt32 WRITE_DATA = 0x10_00_00_02;
    /// <summary>
    /// Jtag Write Command
    /// </summary>
    public const UInt32 WRITE_CMD = 0x10_00_00_03;
    /// <summary>
    /// Jtag Speed Control
    /// </summary>
    public const UInt32 SPEED_CTRL = 0x10_00_00_04;
}

/// <summary>
/// Jtag 状态寄存器的掩码及其确认函数
/// </summary>
public static class JtagState
{

    /*
    [0]    移位数据读fifo清空，1为有效，清空后自动置0
    [1]    移位数据fifo读入口-空标识，只读，对JTAG_STATE_REG的写不改变其值
    [2]    移位数据fifo读入口-满标识，只读，对JTAG_STATE_REG的写不改变其值
    [7:3]  保留

    [8]    移位数据写fifo清空，1为有效，清空后自动置0
    [9]    移位数据fifo写入口-空标识，只读，对JTAG_STATE_REG的写不改变其值
    [10]   移位数据fifo写入口-满标识，只读，对JTAG_STATE_REG的写不改变其值
    [15:11]保留

    [16]   移位命令写fifo清空，1为有效，清空后自动置0
    [17]   移位命令fifo写入口-空标识，只读，对JTAG_STATE_REG的写不改变其值
    [18]   移位命令fifo写入口-满标识，只读，对JTAG_STATE_REG的写不改变其值
    [23:19]保留

    [24]   CMD执行完毕标识，只读，对JTAG_STATE_REG的写不改变其值
    */

    /// <summary>
    /// 移位数据读fifo清空，1为有效，清空后自动置0，实际一直为零
    /// </summary>
    public const UInt32 READ_DATA_FIFO_CLEAR = 0b0001 << 0;
    /// <summary>
    /// 移位数据fifo读入口-空标识，只读，对JTAG_STATE_REG的写不改变其值
    /// </summary>
    public const UInt32 READ_DATA_FIFO_EMPTY = 0b0010 << 0;
    /// <summary>
    /// 移位数据fifo读入口-满标识，只读，对JTAG_STATE_REG的写不改变其值
    /// </summary>
    public const UInt32 READ_DATA_FIFO_AFULL = 0b0100 << 0;
    /// <summary>
    /// 移位数据读fifo
    /// </summary>
    public const UInt32 READ_DATA_FIFO = 0b0111 << 0;

    /// <summary>
    /// 移位数据写fifo清空，1为有效，清空后自动置0
    /// </summary>
    public const UInt32 WRITE_DATA_FIFO_CLEAR = 0b0001 << 8;
    /// <summary>
    /// 移位数据fifo写入口-空标识，只读，对JTAG_STATE_REG的写不改变其值
    /// </summary>
    public const UInt32 WRITE_DATA_FIFO_EMPTY = 0b0010 << 8;
    /// <summary>
    /// 移位数据fifo写入口-满标识，只读，对JTAG_STATE_REG的写不改变其值
    /// </summary>
    public const UInt32 WRITE_DATA_FIFO_AFULL = 0b0100 << 8;
    /// <summary>
    /// 移位数据写fifo
    /// </summary>
    public const UInt32 WRITE_DATA_FIFO = 0b0111 << 8;

    /// <summary>
    /// 移位命令写fifo清空，1为有效，清空后自动置0
    /// </summary>
    public const UInt32 WRITE_CMD_FIFO_CLEAR = 0b0001 << 16;
    /// <summary>
    /// 移位命令fifo写入口-空标识，只读，对JTAG_STATE_REG的写不改变其值
    /// </summary>
    public const UInt32 WRITE_CMD_FIFO_EMPTY = 0b0010 << 16;
    /// <summary>
    /// 移位命令fifo写入口-满标识，只读，对JTAG_STATE_REG的写不改变其值
    /// </summary>
    public const UInt32 WRITE_CMD_FIFO_AFULL = 0b0100 << 16;
    /// <summary>
    /// 移位命令写fifo
    /// </summary>
    public const UInt32 WRITE_CMD_FIFO = 0b0111 << 16;

    /// <summary>
    /// CMD执行完毕标识，只读，对JTAG_STATE_REG的写不改变其值
    /// </summary>
    public const UInt32 CMD_EXEC_FINISH = 0b0001 << 24;
    /// <summary>
    /// 全部FIFO
    /// </summary>
    public const UInt32 ALL_FIFO = READ_DATA_FIFO | WRITE_DATA_FIFO | WRITE_CMD_FIFO;
    /// <summary>
    /// 全部寄存器
    /// </summary>
    public const UInt32 ALL_REG = READ_DATA_FIFO | WRITE_DATA_FIFO | WRITE_CMD_FIFO | CMD_EXEC_FINISH;

}

/// <summary>
/// The Command bits of Jtag
/// </summary>
public static class JtagCmd
{

    /// <summary>
    /// The length of JTAG_DR_XXXX
    /// </summary>
    public const UInt32 LEN_JTAG_DR = 10;
    /// <summary>
    /// 旁路指令
    /// </summary>
    public const UInt32 JTAG_DR_BYPASS = 0b1111111111;
    /// <summary>
    /// 采样指令
    /// </summary>
    public const UInt32 JTAG_DR_SAMPLE = 0b1010000000;
    /// <summary>
    /// 预装指令
    /// </summary>
    public const UInt32 JTAG_DR_PRELOAD = 0b1010000000;
    /// <summary>
    /// 外测试指令
    /// </summary>
    public const UInt32 JTAG_DR_EXTEST = 0b1010000001;
    /// <summary>
    /// 内测试指令
    /// </summary>
    public const UInt32 JTAG_DR_INTEST = 0b1010000010;
    /// <summary>
    /// 标识指令
    /// </summary>
    public const UInt32 JTAG_DR_IDCODE = 0b1010000011;
    /// <summary>
    /// 高阻指令
    /// </summary>
    public const UInt32 JTAG_DR_HIGHZ = 0b1010000101;
    /// <summary>
    /// 复位指令
    /// </summary>
    public const UInt32 JTAG_DR_JRST = 0b1010001010;
    /// <summary>
    /// 配置指令
    /// </summary>
    public const UInt32 JTAG_DR_CFGI = 0b1010001011;
    /// <summary>
    /// 回读指令
    /// </summary>
    public const UInt32 JTAG_DR_CFGO = 0b1010001100;
    /// <summary>
    /// 唤醒指令
    /// </summary>
    public const UInt32 JTAG_DR_JWAKEUP = 0b1010001101;
    /// <summary>
    /// 读UID指令
    /// </summary>
    public const UInt32 JTAG_DR_READ_UID = 0b0101001100;
    /// <summary>
    /// 读状态寄存器指令
    /// </summary>
    public const UInt32 JTAG_DR_RDSR = 0b0101011001;



    /// <summary>
    /// The length of CMD_JTAG_XXXX_XXXX
    /// </summary>
    public const UInt32 LEN_CMD_JTAG = 4;
    /// <summary>
    /// 设定JTAG默认状态为TEST_LOGIC_RESET态 （JTAG复位）
    /// </summary>
    public const UInt32 CMD_JTAG_CLOSE_TEST = 0b0000;
    /// <summary>
    /// 设定JTAG默认状态为RUN_TEST_IDLE态    （JTAG空闲）
    /// </summary>
    public const UInt32 CMD_JTAG_RUN_TEST = 0b0001;
    /// <summary>
    /// JTAG进入SHIFTIR循环cycle_num次后回到设定的默认状态
    /// </summary>
    public const UInt32 CMD_JTAG_LOAD_IR = 0b0010;
    /// <summary>
    /// JTAG进入SHIFTDR循环cycle_num次后回到设定的默认状态，同时输入shift_in
    /// </summary>
    public const UInt32 CMD_JTAG_LOAD_DR_CAREI = 0b0011;
    /// <summary>
    /// JTAG进入SHIFTDR循环cycle_num次后回到设定的默认状态，同时输出shift_out
    /// </summary>
    public const UInt32 CMD_JTAG_LOAD_DR_CAREO = 0b0100;
    /// <summary>
    /// JTAG进入RUN_TEST_IDLE态循环cycle_num次
    /// </summary>
    public const UInt32 CMD_JTAG_IDLE_DELAY = 0b0101;
}

/// <summary>
/// JTAG 状态寄存器
/// </summary>
public class JtagStatusReg
{
    /// <summary>
    /// ID 错误标志
    /// </summary>
    public bool id_err { get; set; }
    /// <summary>
    /// CRC 错误标志
    /// </summary>
    public bool crc_err { get; set; }
    /// <summary>
    /// 自动测试错误标志
    /// </summary>
    public bool aut_err { get; set; }
    /// <summary>
    /// 回读 CRC 错误标志
    /// </summary>
    public bool rbcrc_err { get; set; }
    /// <summary>
    /// 超时标志
    /// </summary>
    public bool timeout { get; set; }
    /// <summary>
    /// 唤醒完成标志
    /// </summary>
    public bool wakeup_over { get; set; }
    /// <summary>
    /// 休眠完成标志
    /// </summary>
    public bool wakedown_over { get; set; }
    /// <summary>
    /// 模式位
    /// </summary>
    public string m { get; set; }
    /// <summary>
    /// 初始化完成标志
    /// </summary>
    public bool init_complete { get; set; }
    /// <summary>
    /// 初始化状态（低电平有效）
    /// </summary>
    public bool init_n { get; set; }
    /// <summary>
    /// 完成标志
    /// </summary>
    public bool done { get; set; }
    /// <summary>
    /// 内部完成标志
    /// </summary>
    public bool done_i { get; set; }
    /// <summary>
    /// 全局逻辑使能标志
    /// </summary>
    public bool glogen { get; set; }
    /// <summary>
    /// 全局逻辑反馈标志
    /// </summary>
    public bool glogen_fb { get; set; }
    /// <summary>
    /// 全局输出使能标志
    /// </summary>
    public bool gouten { get; set; }
    /// <summary>
    /// 全局复位标志
    /// </summary>
    public bool grsn { get; set; }
    /// <summary>
    /// 全局写使能标志
    /// </summary>
    public bool gwen { get; set; }
    /// <summary>
    /// PLL 锁定标志
    /// </summary>
    public bool pll_lock { get; set; }
    /// <summary>
    /// 回退标志
    /// </summary>
    public bool fallback { get; set; }
    /// <summary>
    /// IPAL 模式位
    /// </summary>
    public string ipal_m { get; set; }
    /// <summary>
    /// 8 位标志
    /// </summary>
    public bool flg_x8 { get; set; }
    /// <summary>
    /// 16 位标志
    /// </summary>
    public bool flg_x16 { get; set; }
    /// <summary>
    /// 32 位标志
    /// </summary>
    public bool flg_x32 { get; set; }
    /// <summary>
    /// 过温标志
    /// </summary>
    public bool over_temp { get; set; }
    /// <summary>
    /// 配置错误标志
    /// </summary>
    public bool prcfg_err { get; set; }
    /// <summary>
    /// 配置完成标志
    /// </summary>
    public bool prcfg_over { get; set; }

    /// <summary>
    /// 构造函数，从 32 位代码解析 JTAG 状态寄存器
    /// </summary>
    /// <param name="code">32 位状态寄存器值</param>
    public JtagStatusReg(UInt32 code)
    {
        this.id_err = Common.Number.ToBit(code, 0).Value;
        this.crc_err = Common.Number.ToBit(code, 1).Value;
        this.aut_err = Common.Number.ToBit(code, 2).Value;
        this.rbcrc_err = Common.Number.ToBit(code, 3).Value;
        this.timeout = Common.Number.ToBit(code, 4).Value;
        this.wakeup_over = Common.Number.ToBit(code, 5).Value;
        this.wakedown_over = Common.Number.ToBit(code, 6).Value;
        this.m = Convert.ToString(((code >> 7) & 0b111), 2);
        this.init_complete = Common.Number.ToBit(code, 10).Value;
        this.init_n = Common.Number.ToBit(code, 11).Value;
        this.done = Common.Number.ToBit(code, 12).Value;
        this.done_i = Common.Number.ToBit(code, 13).Value;
        this.glogen = Common.Number.ToBit(code, 14).Value;
        this.glogen_fb = Common.Number.ToBit(code, 15).Value;
        this.gouten = Common.Number.ToBit(code, 16).Value;
        this.grsn = Common.Number.ToBit(code, 17).Value;
        this.gwen = Common.Number.ToBit(code, 18).Value;
        this.pll_lock = Common.Number.ToBit(code, 19).Value;
        this.fallback = Common.Number.ToBit(code, 21).Value;
        this.ipal_m = Convert.ToString(((code >> 22) & 0b11), 2);
        this.flg_x8 = Common.Number.ToBit(code, 24).Value;
        this.flg_x16 = Common.Number.ToBit(code, 25).Value;
        this.flg_x32 = Common.Number.ToBit(code, 26).Value;
        this.over_temp = Common.Number.ToBit(code, 27).Value;
        this.prcfg_err = Common.Number.ToBit(code, 28).Value;
        this.prcfg_over = Common.Number.ToBit(code, 29).Value;
    }

    /// <summary>
    /// 转换为Json字符串
    /// </summary>
    /// <returns>Json字符串</returns>
    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

/// <summary>
/// Jtag控制器
/// </summary>
public class Jtag
{
    private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    private const int CLOCK_FREQ = 50; // MHz

    readonly int timeout;

    readonly int port;
    /// <summary>
    /// Jtag控制器IP地址
    /// </summary>
    public readonly string address;
    private IPEndPoint ep;

    /// <summary>
    /// Jtag 构造函数
    /// </summary>
    /// <param name="address">目标 IP 地址</param>
    /// <param name="port">目标 UDP 端口</param>
    /// <param name="timeout">超时时间（毫秒）</param>
    public Jtag(string address, int port, int timeout = 2000)
    {
        this.address = address;
        this.port = port;
        this.ep = new IPEndPoint(IPAddress.Parse(address), port);
        this.timeout = timeout;
    }

    async ValueTask<Result<uint>> ReadFIFO(uint devAddr)
    {
        var ret = false;
        var opts = new SendAddrPackOptions()
        {
            BurstType = BurstType.FixedBurst,
            BurstLength = 0,
            CommandID = 0,
            Address = devAddr,
            IsWrite = false,
        };


        // Read Jtag State Register
        ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
        if (!ret) return new(new Exception("Send Address Package Failed!"));

        // Wait for Read Ack
        if (!MsgBus.IsRunning)
            return new(new Exception("Message Bus not Working!"));

        var retPack = await MsgBus.UDPServer.WaitForDataAsync(address, 0, port);
        if (!retPack.IsSuccessful || !retPack.Value.IsSuccessful)
            return new(new Exception("Send address package failed"));

        var retPackOpts = retPack.Value.Options;
        if (retPackOpts.Data is null)
            return new(new Exception($"Data is Null, package: {retPackOpts.ToString()}"));

        var retPackLen = retPackOpts.Data.Length;
        if (retPackLen != 4)
            return new(new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"));

        return Convert.ToUInt32(Common.Number.BytesToUInt32(retPackOpts.Data).Value);
    }

    async ValueTask<Result<bool>> WriteFIFO(
        UInt32 devAddr, UInt32 data, UInt32 result,
        UInt32 resultMask = 0xFF_FF_FF_FF, UInt32 delayMilliseconds = 0, ProgressReporter? progress = null)
    {
        {
            var ret = await UDPClientPool.WriteAddr(this.ep, 0, devAddr, data, this.timeout, progress?.CreateChild(80));
            if (!ret.IsSuccessful) return new(ret.Error);
            if (!ret.Value) return new(new Exception("Write FIFO failed"));
        }

        // Delay some time before read register
        await Task.Delay(TimeSpan.FromMilliseconds(delayMilliseconds));

        {
            var ret = await UDPClientPool.ReadAddrWithWait(this.ep, 0, JtagAddr.STATE, result, resultMask, 0, this.timeout);
            if (!ret.IsSuccessful) return new(ret.Error);
            progress?.Finish();
            return ret.Value;
        }
    }

    async ValueTask<Result<bool>> WriteFIFO(
        UInt32 devAddr, byte[] data, UInt32 result,
        UInt32 resultMask = 0xFF_FF_FF_FF, UInt32 delayMilliseconds = 0, ProgressReporter? progress = null)
    {
        {
            var ret = await UDPClientPool.WriteAddr(this.ep, 0, devAddr, data, this.timeout, progress?.CreateChild(80));
            if (!ret.IsSuccessful) return new(ret.Error);
            if (!ret.Value) return new(new Exception("Write FIFO failed"));
        }

        // Delay some time before read register
        await Task.Delay(TimeSpan.FromMilliseconds(delayMilliseconds));

        {
            var ret = await UDPClientPool.ReadAddrWithWait(this.ep, 0, JtagAddr.STATE, result, resultMask, 0, this.timeout);
            if (!ret.IsSuccessful) return new(ret.Error);
            progress?.Finish();
            return ret.Value;
        }
    }

    /// <summary>
    /// 清除所有 JTAG 寄存器
    /// </summary>
    /// <returns>指示清除是否成功的异步结果</returns>
    async ValueTask<Result<bool>> ClearAllRegisters()
    {
        return await WriteFIFO(JtagAddr.STATE, 0xFF_FF_FF_FF, 0x01_02_02_02, JtagState.ALL_REG);
    }

    /// <summary>
    /// 清除 JTAG 写数据寄存器
    /// </summary>
    /// <returns>指示清除是否成功的异步结果</returns>
    async ValueTask<Result<bool>> ClearWriteDataReg()
    {
        return await WriteFIFO(JtagAddr.STATE, 0x00_00_11_00, 0x01_00_02_00, JtagState.WRITE_DATA_FIFO | JtagState.CMD_EXEC_FINISH);
    }

    /// <summary>
    /// 关闭 JTAG 测试模式
    /// </summary>
    /// <returns>指示操作是否成功的异步结果</returns>
    async ValueTask<Result<bool>> CloseTest()
    {
        return await WriteFIFO(
                JtagAddr.WRITE_CMD,
                Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_CLOSE_TEST, JtagCmd.LEN_CMD_JTAG, 0, 28).Value,
                0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
    }

    /// <summary>
    /// 启动 JTAG 测试模式
    /// </summary>
    /// <returns>指示操作是否成功的异步结果</returns>
    async ValueTask<Result<bool>> RunTest()
    {
        return await WriteFIFO(
                JtagAddr.WRITE_CMD,
                Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_RUN_TEST, JtagCmd.LEN_CMD_JTAG, 0, 28).Value,
                0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
    }

    /// <summary>
    /// 设置 JTAG 空闲延迟时间
    /// </summary>
    /// <param name="milliseconds">延迟时间（毫秒）</param>
    /// <returns>指示操作是否成功的异步结果</returns>
    async ValueTask<Result<bool>> IdleDelay(UInt32 milliseconds)
    {
        if (milliseconds > Math.Pow(2, 28)) return new(new Exception("Timespan is over 2^28 milliseconds"));

        return await WriteFIFO(
                JtagAddr.WRITE_CMD,
                Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_IDLE_DELAY, JtagCmd.LEN_CMD_JTAG, milliseconds, 28).Value,
                0x01_00_00_00, JtagState.CMD_EXEC_FINISH, (milliseconds / CLOCK_FREQ) + 100);
    }

    async ValueTask<Result<bool>> ExecRDCmd(uint command)
    {
        {
            var ret = await WriteFIFO(
                JtagAddr.WRITE_DATA,
                Common.Number.MultiBitsToNumber(0, 22, command, JtagCmd.LEN_JTAG_DR).Value, 0, 0);

            if (!ret.IsSuccessful) return new(ret.Error);
            else if (!ret.Value) return new(new Exception("Write JTAG_DR_IDCODE Failed"));
        }
        {
            var ret = await WriteFIFO(
                JtagAddr.WRITE_CMD,
                Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_IR, JtagCmd.LEN_CMD_JTAG, 10, 28).Value,
                0x01_00_00_00, JtagState.CMD_EXEC_FINISH);

            if (!ret.IsSuccessful) return new(ret.Error);
            else if (!ret.Value) return new(new Exception("Write CMD_JTAG_LOAD_IR Failed"));
        }
        return await ClearWriteDataReg();
    }

    async ValueTask<Result<bool>> LoadDRCareInput(
        byte[] bytesArray, UInt32 timeout = 10_000, UInt32 cycle = 500, ProgressReporter? progress = null)
    {
        var bytesLen = ((uint)(bytesArray.Length * 8));
        if (bytesLen > Math.Pow(2, 28)) return new(new Exception("Length is over 2^(28 - 3)"));

        {
            var ret = await WriteFIFO(
                    JtagAddr.WRITE_CMD,
                    Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREI, JtagCmd.LEN_CMD_JTAG, bytesLen, 28).Value,
                    0, 0);

            if (!ret.IsSuccessful) return new(ret.Error);
            else if (!ret.Value) return new(new Exception("Write CMD_JTAG_LOAD_DR_CAREI Failed"));
        }

        progress?.Report(10);

        {
            var ret = await WriteFIFO(
                JtagAddr.WRITE_DATA,
                bytesArray, 0x01_00_00_00,
                JtagState.CMD_EXEC_FINISH,
                progress: progress?.CreateChild(90)
            );

            if (!ret.IsSuccessful) return new(ret.Error);
            return ret.Value;
        }
    }

    async ValueTask<Result<UInt32>> LoadDRCareOutput(UInt32 UInt32Num)
    {
        if (UInt32Num > Math.Pow(2, 23)) return new(new Exception("Length is over 2^(28 - 5)"));

        var ret = await WriteFIFO(
                JtagAddr.WRITE_CMD,
                Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREO, JtagCmd.LEN_CMD_JTAG, 32 * UInt32Num, 28).Value,
                0x01_00_00_00, JtagState.CMD_EXEC_FINISH);

        if (ret.Value)
            return await ReadFIFO(JtagAddr.READ_DATA);
        else
            return new(new Exception("LoadDRCareo Failed!"));
    }

    async ValueTask<Result<UInt32[]>> LoadDRCareOutputArray(UInt32 UInt32Num)
    {
        if (UInt32Num > Math.Pow(2, 23)) return new(new Exception("Length is over 2^(28 - 5)"));

        var ret = await WriteFIFO(
                JtagAddr.WRITE_CMD,
                Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREO, JtagCmd.LEN_CMD_JTAG, 32 * UInt32Num, 28).Value,
                JtagState.CMD_EXEC_FINISH, JtagState.CMD_EXEC_FINISH);

        if (ret.Value)
        {
            var array = new UInt32[UInt32Num];
            var retData = await UDPClientPool.ReadAddr4Bytes(ep, 0, JtagAddr.READ_DATA, (int)UInt32Num);
            if (!retData.IsSuccessful)
                return new(new Exception("Read FIFO failed when Load DR"));
            Buffer.BlockCopy(retData.Value, 0, array, 0, (int)UInt32Num * 4);
            return array;
        }
        else
            return new(new Exception("LoadDRCareo Failed!"));
    }

    /// <summary>
    /// 读取 JTAG 设备的 ID 代码
    /// </summary>
    /// <returns>包含 ID 代码的异步结果</returns>
    public async ValueTask<Result<uint>> ReadIDCode()
    {
        // Clear Data
        MsgBus.UDPServer.ClearUDPData(this.address, 0);

        logger.Trace($"Clear up udp server {this.address,0} receive data");

        Result<bool> ret;

        ret = await ClearAllRegisters();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Clear All Registers Failed"));

        ret = await RunTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));

        ret = await ExecRDCmd(JtagCmd.JTAG_DR_IDCODE);
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_IDCODE Failed"));

        ret = await ClearWriteDataReg();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Clear Write Registers Failed"));

        var retData = await LoadDRCareOutput(1);
        if (!retData.IsSuccessful)
        {
            return new(new Exception("Get ID Code Failed"));
        }

        return retData.Value;
    }

    /// <summary>
    /// 读取 JTAG 设备的状态寄存器
    /// </summary>
    /// <returns>包含状态寄存器值的异步结果</returns>
    public async ValueTask<Result<uint>> ReadStatusReg()
    {
        // Clear Data
        MsgBus.UDPServer.ClearUDPData(this.address, 0);

        logger.Trace($"Clear up udp server {this.address,0} receive data");

        Result<bool> ret;

        ret = await ClearAllRegisters();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Clear All Registers Failed"));

        ret = await RunTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));

        ret = await ExecRDCmd(JtagCmd.JTAG_DR_RDSR);
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_RDSR Failed"));

        ret = await ClearWriteDataReg();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Clear Write Registers Failed"));

        var retData = await LoadDRCareOutput(1);
        if (!retData.IsSuccessful)
            return new(new Exception("Read Status Reg Failed"));

        return retData.Value;
    }

    /// <summary>
    /// 下载比特流到 JTAG 设备
    /// </summary>
    /// <param name="bitstream">比特流数据</param>
    /// <returns>指示下载是否成功的异步结果</returns>
    public async ValueTask<Result<bool>> DownloadBitstream(byte[] bitstream, ProgressReporter? progress = null)
    {
        // Clear Data
        MsgBus.UDPServer.ClearUDPData(this.address, 0);

        logger.Trace($"Clear up udp server {this.address,0} receive data");
        if (progress != null)
        {
            progress.ExpectedSteps = 25;
            progress.Increase();
        }

        Result<bool> ret;

        ret = await CloseTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
        progress?.Increase();

        ret = await RunTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
        progress?.Increase();

        logger.Trace("Jtag initialize");

        ret = await ExecRDCmd(JtagCmd.JTAG_DR_JRST);
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_JRST Failed"));
        progress?.Increase();

        ret = await RunTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
        progress?.Increase();

        ret = await ExecRDCmd(JtagCmd.JTAG_DR_CFGI);
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_CFGI Failed"));
        progress?.Increase();

        logger.Trace("Jtag ready to write bitstream");

        ret = await IdleDelay(100000);
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag IDLE Delay Failed"));
        progress?.Increase();

        ret = await LoadDRCareInput(bitstream, progress: progress?.CreateChild(50));
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Load Data Failed"));

        logger.Trace("Jtag write bitstream");

        ret = await CloseTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
        progress?.Increase();

        ret = await RunTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
        progress?.Increase();

        ret = await ExecRDCmd(JtagCmd.JTAG_DR_JWAKEUP);
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_JWAKEUP Failed"));
        progress?.Increase();

        logger.Trace("Jtag reset device");

        ret = await IdleDelay(10000);
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag IDLE Delay Failed"));
        progress?.Increase();

        var retCode = await ReadStatusReg();
        if (!retCode.IsSuccessful) return new(retCode.Error);
        var jtagStatus = new JtagStatusReg(retCode.Value);
        if (!(jtagStatus.done && jtagStatus.wakeup_over && jtagStatus.init_complete))
            return new(new Exception("Jtag download bitstream failed"));
        progress?.Increase();

        ret = await CloseTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
        logger.Trace("Jtag download bitstream successfully");
        progress?.Increase();

        // Finish
        progress?.Finish();
        return true;
    }


    /// <summary>
    /// 边界扫描
    /// </summary>
    /// <returns>返回所有引脚边界扫描结果</returns>
    public async ValueTask<Result<BitArray>> BoundaryScan()
    {
        var paser = new BsdlParser.Parser();
        var portNum = paser.GetBoundaryRegsNum().Value;
        logger.Debug($"Get boundary scan registers number: {portNum}");

        // Clear Data
        MsgBus.UDPServer.ClearUDPData(this.address, 0);

        logger.Trace($"Clear up udp server {this.address,0} receive data");

        Result<bool> ret;

        ret = await CloseTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));

        ret = await RunTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));

        logger.Trace("Jtag initialize");

        ret = await ExecRDCmd(JtagCmd.JTAG_DR_SAMPLE);
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_SAMPLE Failed"));

        var retData = await LoadDRCareOutputArray(((uint)(portNum % 32 == 0 ? portNum / 32 : portNum / 32 + 1)));
        if (!retData.IsSuccessful) return new(retData.Error);

        ret = await CloseTest();
        if (!ret.IsSuccessful) return new(ret.Error);
        else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));

        var byteArray = Common.Number.UInt32ArrayToBytes(retData.Value);
        if (!byteArray.IsSuccessful) return new(byteArray.Error);

        var bitArray = new BitArray(byteArray.Value);
        if (bitArray is null)
            return new(new Exception($"Convert to BitArray failed"));
        bitArray.Length = portNum;
        return bitArray;
    }

    /// <summary>
    /// 执行边界扫描并返回逻辑端口的状态
    /// </summary>
    /// <returns>包含逻辑端口状态的字典，键为端口ID，值为布尔状态</returns>
    public async ValueTask<Result<Dictionary<string, bool>>> BoundaryScanLogicalPorts()
    {
        var bitArray = await BoundaryScan();
        if (!bitArray.IsSuccessful) return new(bitArray.Error);

        var paser = new BsdlParser.Parser();
        var cellList = paser.GetBoundaryLogicalPorts();
        if (cellList.IsNull) return new(new Exception("Get boundary logical ports failed"));

        var portStatus = new Dictionary<string, bool>();
        foreach (var cell in cellList.Value)
        {
            portStatus.Add(cell.PortID ?? "UnknownPortID", bitArray.Value[cell.CellNumber]);
        }

        return portStatus;
    }

    /// <summary>
    /// 设置JTAG的运行速度。
    /// </summary>
    /// <param name="speed">运行速度值。</param>
    /// <returns>指示操作是否成功的异步结果。</returns>
    public async ValueTask<Result<bool>> SetSpeed(UInt32 speed)
    {
        // Clear Data
        MsgBus.UDPServer.ClearUDPData(this.address, 0);

        logger.Trace($"Clear up udp server {this.address,0} receive data");

        var ret = await WriteFIFO(
            JtagAddr.SPEED_CTRL, (speed << 16) | speed,
            JtagState.CMD_EXEC_FINISH, JtagState.CMD_EXEC_FINISH);

        if (!ret.IsSuccessful) return new(ret.Error);
        return ret.Value;
    }
}
