using System.Net;
using Common;
using DotNext;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using WebProtocol;

namespace server.Controllers;

/// <summary>
/// UDP API 
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class UDPController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    private const string LOCALHOST = "127.0.0.1";

    /// <summary>
    /// 页面
    /// </summary>
    [HttpGet]
    public string Index()
    {
        return "This is UDP Controller";
    }

    /// <summary>
    /// 发送字符串
    /// </summary>
    /// <param name="address">IPV4 或者 IPV6 地址</param>
    /// <param name="port">设备端口号</param>
    /// <param name="text">发送的文本</param>
    /// <response code="200">发送成功</response>
    /// <response code="500">发送失败</response>
    [HttpPost("SendString")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> SendString(string address = LOCALHOST, int port = 1234, string text = "Hello Server!")
    {
        var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
        var ret = await UDPClientPool.SendStringAsync(endPoint, [text]);

        if (ret) { return TypedResults.Ok(); }
        else { return TypedResults.InternalServerError(); }
    }

    /// <summary>
    /// 发送二进制数据
    /// </summary>
    /// <param name="address" example="127.0.0.1">IPV4 或者 IPV6 地址</param>
    /// <param name="port" example="1234">设备端口号</param>
    /// <param name="bytes" example="FFFFAAAA">16进制文本</param>
    [HttpPost("SendBytes")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> SendBytes(string address, int port, string bytes)
    {
        var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
        var ret = await UDPClientPool.SendBytesAsync(endPoint, Number.StringToBytes(bytes));

        if (ret) { return TypedResults.Ok(); }
        else { return TypedResults.InternalServerError(); }
    }


    /// <summary>
    /// 发送地址包
    /// </summary>
    /// <param name="address">IP地址</param>
    /// <param name="port">UDP 端口号</param>
    /// <param name="opts">地址包选项</param>
    [HttpPost("SendAddrPackage")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> SendAddrPackage(
        string address,
        int port,
        [FromBody] SendAddrPackOptions opts)
    {
        var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
        var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts));

        if (ret) { return TypedResults.Ok(); }
        else { return TypedResults.InternalServerError(); }
    }

    /// <summary>
    /// 发送数据包
    /// </summary>
    /// <param name="address">IP地址</param>
    /// <param name="port">UDP 端口号</param>
    /// <param name="data">16进制数据</param>
    [HttpPost("SendDataPackage")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> SendDataPackage(string address, int port, string data)
    {
        var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
        var ret = await UDPClientPool.SendDataPackAsync(endPoint,
            new WebProtocol.SendDataPackage(Number.StringToBytes(data)));

        if (ret) { return TypedResults.Ok(); }
        else { return TypedResults.InternalServerError(); }
    }

    /// <summary>
    /// 获取指定IP地址接受的数据列表
    /// </summary>
    /// <param name="address">IP地址</param>
    [HttpGet("GetRecvDataArray")]
    [ProducesResponseType(typeof(List<UDPData>), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> GetRecvDataArray(string address)
    {
        var ret = await MsgBus.UDPServer.GetDataArrayAsync(address);

        if (ret.HasValue)
        {
            var dataJson = JsonConvert.SerializeObject(ret.Value);
            logger.Debug($"Get Receive Successfully: {dataJson}");

            return TypedResults.Ok(ret.Value);
        }
        else
        {
            logger.Debug("Get Receive Failed");
            return TypedResults.InternalServerError();
        }
    }

}

/// <summary>
/// Jtag API
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class JtagController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    private const string BITSTREAM_PATH = "bitstream/Jtag";

    /// <summary>
    /// 页面
    /// </summary>
    [HttpGet]
    public string Index()
    {
        return "This is Jtag Controller";
    }

    /// <summary>
    /// 获取Jtag ID Code
    /// </summary>
    /// <param name="address"> 设备地址 </param>
    /// <param name="port"> 设备端口 </param>
    [HttpGet("GetDeviceIDCode")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(uint), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> GetDeviceIDCode(string address, int port)
    {
        var jtagCtrl = new JtagClient.Jtag(address, port);
        var ret = await jtagCtrl.ReadIDCode();

        if (ret.IsSuccessful)
        {
            logger.Info($"Get device {address} ID code: 0x{ret.Value:X4}");
            return TypedResults.Ok(ret.Value);
        }
        else
        {
            logger.Error(ret.Error);
            return TypedResults.InternalServerError(ret.Error);
        }
    }

    /// <summary>
    /// 获取状态寄存器
    /// </summary>
    /// <param name="address"> 设备地址 </param>
    /// <param name="port"> 设备端口 </param>
    [HttpGet("ReadStatusReg")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> ReadStatusReg(string address, int port)
    {
        var jtagCtrl = new JtagClient.Jtag(address, port);
        var ret = await jtagCtrl.ReadStatusReg();

        if (ret.IsSuccessful)
        {
            var binaryValue = Common.String.Reverse(Convert.ToString(ret.Value, 2).PadLeft(32, '0'));
            var decodeValue = new JtagClient.JtagStatusReg(ret.Value);
            logger.Info($"Read device {address} Status Register: \n\t 0b{binaryValue} \n\t {decodeValue}");
            return TypedResults.Ok(new
            {
                original = ret.Value,
                binaryValue,
                decodeValue,
            });
        }
        else
        {
            logger.Error(ret.Error);
            return TypedResults.InternalServerError(ret.Error);
        }
    }

    /// <summary>
    /// 上传比特流文件
    /// </summary>
    /// <param name="address"> 设备地址 </param>
    /// <param name="file">比特流文件</param>
    [HttpPost("UploadBitstream")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
    public async ValueTask<IResult> UploadBitstream(string address, IFormFile file)
    {
        if (file == null || file.Length == 0)
            return TypedResults.BadRequest("未选择文件");

        // 生成安全的文件名（避免路径遍历攻击）
        var fileName = Path.GetRandomFileName();
        var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");

        // 如果存在文件，则删除原文件再上传
        if (Directory.Exists(uploadsFolder))
        {
            Directory.Delete(uploadsFolder, true);
        }
        Directory.CreateDirectory(uploadsFolder);

        var filePath = Path.Combine(uploadsFolder, fileName);

        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }

        logger.Info($"Device {address} Upload Bitstream Successfully");
        return TypedResults.Ok(true);
    }

    /// <summary>
    /// 通过Jtag下载比特流文件
    /// </summary>
    /// <param name="address"> 设备地址 </param>
    /// <param name="port"> 设备端口 </param>
    [HttpPost("DownloadBitstream")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> DownloadBitstream(string address, int port)
    {
        // 检查文件
        var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");
        if (!Directory.Exists(fileDir))
            return TypedResults.BadRequest("Empty bitstream, Please upload it first");

        try
        {
            // 读取文件
            var filePath = Directory.GetFiles(fileDir)[0];

            using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open))
            {
                if (fileStream is null || fileStream.Length <= 0)
                    return TypedResults.BadRequest("Wrong bitstream, Please upload it again");

                // 定义缓冲区大小: 32KB
                byte[] buffer = new byte[32 * 1024];
                byte[] revBuffer = new byte[32 * 1024];
                long totalBytesRead = 0;

                // 使用异步流读取文件
                using (var memoryStream = new MemoryStream())
                {
                    int bytesRead;
                    while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        // 反转 32bits
                        var retBuffer = Common.Number.ReverseBytes(buffer, 4);
                        if (!retBuffer.IsSuccessful)
                            return TypedResults.InternalServerError(retBuffer.Error);
                        revBuffer = retBuffer.Value;

                        for (int i = 0; i < revBuffer.Length; i++)
                        {
                            revBuffer[i] = Common.Number.ReverseBits(revBuffer[i]);
                        }

                        await memoryStream.WriteAsync(revBuffer, 0, bytesRead);
                        totalBytesRead += bytesRead;
                    }

                    // 将所有数据转换为字节数组（注意：如果文件非常大，可能不适合完全加载到内存）
                    var fileBytes = memoryStream.ToArray();

                    // 下载比特流
                    var jtagCtrl = new JtagClient.Jtag(address, port);
                    var ret = await jtagCtrl.DownloadBitstream(fileBytes);

                    if (ret.IsSuccessful)
                    {
                        logger.Info($"Device {address} dowload bitstream successfully");
                        return TypedResults.Ok(ret.Value);
                    }
                    else
                    {
                        logger.Error(ret.Error);
                        return TypedResults.InternalServerError(ret.Error);
                    }
                }

            }

        }
        catch (Exception error)
        {
            return TypedResults.InternalServerError(error);
        }
        finally
        {

        }
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <param name="address">[TODO:parameter]</param>
    /// <param name="port">[TODO:parameter]</param>
    /// <returns>[TODO:return]</returns>
    [HttpPost("BoundaryScanAllPorts")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> BoundaryScanAllPorts(string address, int port)
    {
        var jtagCtrl = new JtagClient.Jtag(address, port);
        var ret = await jtagCtrl.BoundaryScan();
        if (!ret.IsSuccessful)
        {
            if (ret.Error is ArgumentException)
                return TypedResults.BadRequest(ret.Error);
            else return TypedResults.InternalServerError(ret.Error);
        }

        return TypedResults.Ok(ret.Value);
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <param name="address">[TODO:parameter]</param>
    /// <param name="port">[TODO:parameter]</param>
    /// <returns>[TODO:return]</returns>
    [HttpPost("BoundaryScanLogicalPorts")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(Dictionary<string, bool>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> BoundaryScanLogicalPorts(string address, int port)
    {
        var jtagCtrl = new JtagClient.Jtag(address, port);
        var ret = await jtagCtrl.BoundaryScanLogicalPorts();
        if (!ret.IsSuccessful)
        {
            if (ret.Error is ArgumentException)
                return TypedResults.BadRequest(ret.Error);
            else return TypedResults.InternalServerError(ret.Error);
        }

        return TypedResults.Ok(ret.Value);
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <param name="address">[TODO:parameter]</param>
    /// <param name="port">[TODO:parameter]</param>
    /// <param name="speed">[TODO:parameter]</param>
    /// <returns>[TODO:return]</returns>
    [HttpPost("SetSpeed")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> SetSpeed(string address, int port, UInt32 speed)
    {
        var jtagCtrl = new JtagClient.Jtag(address, port);
        var ret = await jtagCtrl.SetSpeed(speed);
        if (!ret.IsSuccessful)
        {
            if (ret.Error is ArgumentException)
                return TypedResults.BadRequest(ret.Error);
            else return TypedResults.InternalServerError(ret.Error);
        }

        return TypedResults.Ok(ret.Value);
    }
}

/// <summary>
/// 远程更新
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class RemoteUpdateController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    private const string BITSTREAM_PATH = "bitstream/RemoteUpdate";

    /// <summary>
    /// 上传远程更新比特流文件
    /// </summary>
    /// <param name="address"> 设备地址 </param>
    /// <param name="goldenBitream">黄金比特流文件</param>
    /// <param name="bitstream1">比特流文件1</param>
    /// <param name="bitstream2">比特流文件2</param>
    /// <param name="bitstream3">比特流文件3</param>
    /// <returns>上传结果</returns>
    [HttpPost("UploadBitstream")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)]
    public async ValueTask<IResult> UploadBitstreams(
        string address,
        IFormFile? goldenBitream,
        IFormFile? bitstream1,
        IFormFile? bitstream2,
        IFormFile? bitstream3)
    {
        if ((goldenBitream is null || goldenBitream.Length == 0) &&
            (bitstream1 is null || bitstream1.Length == 0) &&
            (bitstream2 is null || bitstream2.Length == 0) &&
            (bitstream3 is null || bitstream3.Length == 0))
            return TypedResults.BadRequest("未选择文件");

        // 生成安全的文件名（避免路径遍历攻击）
        var fileName = Path.GetRandomFileName();
        var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");

        // 如果存在文件，则删除原文件再上传
        if (Directory.Exists(uploadsFolder))
        {
            Directory.Delete(uploadsFolder, true);
        }
        Directory.CreateDirectory(uploadsFolder);

        for (int bitstreamNum = 0; bitstreamNum < 4; bitstreamNum++)
        {
            IFormFile file;
            if (bitstreamNum == 0 && goldenBitream is not null)
                file = goldenBitream;
            else if (bitstreamNum == 1 && bitstream1 is not null)
                file = bitstream1;
            else if (bitstreamNum == 2 && bitstream2 is not null)
                file = bitstream2;
            else if (bitstreamNum == 3 && bitstream3 is not null)
                file = bitstream3;
            else continue;

            var fileFolder = Path.Combine(uploadsFolder, bitstreamNum.ToString());
            Directory.CreateDirectory(fileFolder);

            var filePath = Path.Combine(fileFolder, fileName);

            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }
        }

        logger.Info($"Device {address} Upload Bitstream Successfully");
        return TypedResults.Ok(true);
    }

    private async ValueTask<Result<byte[]>> ProcessBitstream(string filePath)
    {
        using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open))
        {
            if (fileStream is null || fileStream.Length <= 0)
                return new(new ArgumentException("Wrong bitstream path"));

            // 定义缓冲区大小: 32KB
            byte[] buffer = new byte[32 * 1024];
            byte[] revBuffer = new byte[32 * 1024];
            long totalBytesRead = 0;

            // 使用异步流读取文件
            using (var memoryStream = new MemoryStream())
            {
                int bytesRead;
                while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                {
                    // 反转 32bits
                    var retBuffer = Common.Number.ReverseBytes(buffer, 4);
                    if (!retBuffer.IsSuccessful)
                        return new(retBuffer.Error);
                    revBuffer = retBuffer.Value;

                    await memoryStream.WriteAsync(revBuffer, 0, bytesRead);
                    totalBytesRead += bytesRead;
                }

                // 将所有数据转换为字节数组（注意：如果文件非常大，可能不适合完全加载到内存）
                var restStreamLen = memoryStream.Length % (4 * 1024);
                if (restStreamLen != 0)
                {
                    var appendLen = ((int)(4 * 1024 - restStreamLen));
                    var bytesAppend = new byte[appendLen];
                    Array.Fill<byte>(bytesAppend, 0xFF);
                    await memoryStream.WriteAsync(bytesAppend, 0, appendLen);
                }

                return new(memoryStream.ToArray());
            }
        }
    }

    /// <summary>
    /// 远程更新单个比特流文件
    /// </summary>
    /// <param name="address"> 设备地址 </param>
    /// <param name="port"> 设备端口 </param>
    /// <param name="bitstreamNum"> 比特流位号 </param>
    [HttpPost("DownloadBitstream")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> UpdateBitstream(string address, int port, int bitstreamNum)
    {
        // 检查文件
        var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}/{bitstreamNum}");
        if (!Directory.Exists(fileDir))
            return TypedResults.BadRequest("Empty bitstream, Please upload it first");

        try
        {
            // 读取文件
            var filePath = Directory.GetFiles(fileDir)[0];

            var fileBytes = await ProcessBitstream(filePath);
            if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error);

            // 下载比特流
            var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port);
            var ret = await remoteUpdater.UpdateBitstream(bitstreamNum, fileBytes.Value);

            if (ret.IsSuccessful)
            {
                logger.Info($"Device {address} Update bitstream successfully");
                return TypedResults.Ok(ret.Value);
            }
            else
            {
                logger.Error(ret.Error);
                return TypedResults.InternalServerError(ret.Error);
            }

        }
        catch (Exception error)
        {
            return TypedResults.InternalServerError(error);
        }
    }


    /// <summary>
    /// 下载多个比特流文件
    /// </summary>
    /// <param name="address">设备地址</param>
    /// <param name="port">设备端口</param>
    /// <param name="bitstreamNum">比特流编号</param>
    /// <returns>总共上传比特流的数量</returns>
    [HttpPost("DownloadMultiBitstreams")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> DownloadMultiBitstreams(string address, int port, int? bitstreamNum)
    {
        // 检查文件
        var bitstreamsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");
        if (!Directory.Exists(bitstreamsFolder))
            return TypedResults.BadRequest("Empty bitstream, Please upload it first");

        try
        {
            var bitstreams = new List<byte[]?>() { null, null, null, null };
            int cnt = 0; // 上传比特流数量
            for (int i = 0; i < 4; i++)
            {
                var bitstreamDir = Path.Combine(bitstreamsFolder, i.ToString());
                if (!Directory.Exists(bitstreamDir))
                    continue;
                cnt++;

                // 读取文件
                var filePath = Directory.GetFiles(bitstreamDir)[0];
                var fileBytes = await ProcessBitstream(filePath);
                if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error);
                bitstreams[i] = fileBytes.Value;
            }

            // 下载比特流
            var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port);
            {
                var ret = await remoteUpdater.UploadBitstreams(bitstreams[0], bitstreams[1], bitstreams[2], bitstreams[3]);
                if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error);
                if (!ret.Value) return TypedResults.InternalServerError("Upload MultiBitstreams failed");
            }

            if (bitstreamNum is not null)
            {
                var ret = await remoteUpdater.HotResetBitstream(bitstreamNum ?? 0);
                if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error);
                if (!ret.Value) return TypedResults.InternalServerError("Hot reset failed");
            }
            return TypedResults.Ok(cnt);
        }
        catch (Exception error)
        {
            return TypedResults.InternalServerError(error);
        }
    }


    /// <summary>
    /// 热复位比特流文件
    /// </summary>
    /// <param name="address">设备地址</param>
    /// <param name="port">设备端口</param>
    /// <param name="bitstreamNum">比特流编号</param>
    /// <returns>操作结果</returns>
    [HttpPost("HotResetBitstream")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> HotResetBitstream(string address, int port, int bitstreamNum)
    {
        var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port);
        var ret = await remoteUpdater.HotResetBitstream(bitstreamNum);

        if (ret.IsSuccessful)
        {
            logger.Info($"Device {address} Update bitstream successfully");
            return TypedResults.Ok(ret.Value);
        }
        else
        {
            logger.Error(ret.Error);
            return TypedResults.InternalServerError(ret.Error);
        }
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <param name="address">[TODO:parameter]</param>
    /// <param name="port">[TODO:parameter]</param>
    /// <returns>[TODO:return]</returns>
    [HttpPost("GetFirmwareVersion")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(UInt32), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> GetFirmwareVersion(string address, int port)
    {
        var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port);
        var ret = await remoteUpdater.GetVersion();

        if (ret.IsSuccessful)
        {
            logger.Info($"Device {address} get firmware version successfully");
            return TypedResults.Ok(ret.Value);
        }
        else
        {
            logger.Error(ret.Error);
            return TypedResults.InternalServerError(ret.Error);
        }
    }

}

/// <summary>
/// [TODO:description]
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class DDSController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <param name="address">[TODO:parameter]</param>
    /// <param name="port">[TODO:parameter]</param>
    /// <param name="channelNum">[TODO:parameter]</param>
    /// <param name="waveNum">[TODO:parameter]</param>
    /// <returns>[TODO:return]</returns>
    [HttpPost("SetWaveNum")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> SetWaveNum(string address, int port, int channelNum, int waveNum)
    {
        var dds = new DDSClient.DDS(address, port);

        var ret = await dds.SetWaveNum(channelNum, waveNum);
        if (ret.IsSuccessful)
        {
            logger.Info($"Device {address} set output wave num successfully");
            return TypedResults.Ok(ret.Value);
        }
        else
        {
            logger.Error(ret.Error);
            return TypedResults.InternalServerError(ret.Error);
        }
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <param name="address">[TODO:parameter]</param>
    /// <param name="port">[TODO:parameter]</param>
    /// <param name="channelNum">[TODO:parameter]</param>
    /// <param name="waveNum">[TODO:parameter]</param>
    /// <param name="step">[TODO:parameter]</param>
    /// <returns>[TODO:return]</returns>
    [HttpPost("SetFreq")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> SetFreq(string address, int port, int channelNum, int waveNum, UInt32 step)
    {
        var dds = new DDSClient.DDS(address, port);

        var ret = await dds.SetFreq(channelNum, waveNum, step);
        if (ret.IsSuccessful)
        {
            logger.Info($"Device {address} set output freqency successfully");
            return TypedResults.Ok(ret.Value);
        }
        else
        {
            logger.Error(ret.Error);
            return TypedResults.InternalServerError(ret.Error);
        }
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <param name="address">[TODO:parameter]</param>
    /// <param name="port">[TODO:parameter]</param>
    /// <param name="channelNum">[TODO:parameter]</param>
    /// <param name="waveNum">[TODO:parameter]</param>
    /// <param name="phase">[TODO:parameter]</param>
    /// <returns>[TODO:return]</returns>
    [HttpPost("SetPhase")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async ValueTask<IResult> SetPhase(string address, int port, int channelNum, int waveNum, int phase)
    {
        var dds = new DDSClient.DDS(address, port);

        var ret = await dds.SetPhase(channelNum, waveNum, phase);
        if (ret.IsSuccessful)
        {
            logger.Info($"Device {address} set output phase successfully");
            return TypedResults.Ok(ret.Value);
        }
        else
        {
            logger.Error(ret.Error);
            return TypedResults.InternalServerError(ret.Error);
        }

    }

}


/// <summary>
/// [TODO:description]
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class BsdlParserController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    [EnableCors("Development")]
    [HttpGet("GetBoundaryLogicalPorts")]
    public IResult GetBoundaryLogicalPorts()
    {
        var parser = new BsdlParser.Parser();
        var ret = parser.GetBoundaryLogicalPorts();
        if (ret.IsNull) return TypedResults.InternalServerError("Get Null");
        return TypedResults.Ok(ret.Value);
    }
}


/// <summary>
/// 数据控制器
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    /// <summary>
    /// 创建数据库表
    /// </summary>
    /// <returns>插入的记录数</returns>
    [EnableCors("Development")]
    [HttpPost("CreateTable")]
    public IResult CreateTables()
    {
        using var db = new Database.AppDataConnection();
        db.CreateAllTables();
        return TypedResults.Ok();
    }

    /// <summary>
    /// 删除数据库表
    /// </summary>
    /// <returns>插入的记录数</returns>
    [EnableCors("Development")]
    [HttpDelete("DropTables")]
    public IResult DropTables()
    {
        using var db = new Database.AppDataConnection();
        db.DropAllTables();
        return TypedResults.Ok();
    }

    /// <summary>
    /// 获取所有用户
    /// </summary>
    /// <returns>用户列表</returns>
    [HttpGet("AllUsers")]
    public IResult AllUsers()
    {
        using var db = new Database.AppDataConnection();
        var ret = db.User.ToList();
        return TypedResults.Ok(ret);
    }

    /// <summary>
    /// 注册新用户
    /// </summary>
    /// <param name="name">用户名</param>
    /// <returns>操作结果</returns>
    [HttpPost("SignUpUser")]
    public IResult SignUpUser(string name)
    {
        if (name.Length > 255)
            return TypedResults.BadRequest("Name Couln't over 255 characters");

        using var db = new Database.AppDataConnection();
        var ret = db.AddUser(name);
        return TypedResults.Ok(ret);
    }
}

