@page "/add/drawer"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Util;
@using Microsoft.Extensions.Options;
@using Newtonsoft.Json;
@using log4net;
<style>
    .rz-custom-header {
        width: 100%;
    }
</style>
<RadzenStack Orientation="Orientation.Horizontal">
    <div class="row  justify-content-center">
        @if (DrawerNos.Count() > 8)
        {
            <div class="col-12 row justify-content-center align-items-center text-center" style="background: url('/images/box-16.jpg')  no-repeat; background-size: 100% 100%; width: 380px; height:650px">
                <div class="row justify-content-around align-items-center" style="margin-top: 220px; height: 430px;">
                    @foreach (int i in DrawerNos)
                    {
                        if (setting.Value.returnDrawer != null && setting.Value.returnDrawer.Contains(i))
                        {
                            <RadzenButton class="col-5" Click="@(() => SelectDrawer(i))" Text="@i.ToString()" Disabled="true" Shade="Shade.Light" Variant="@(drawerNo !=i ? Variant.Outlined : Variant.Flat)" Style="background-color: #d3d3d3;" />
                        }
                        else
                        {
                            <RadzenButton class="col-5" Click="@(() => SelectDrawer(i))" Text="@i.ToString()" Disabled="@(status > 0)" Shade="Shade.Light" Variant="@(drawerNo !=i ? Variant.Outlined : Variant.Flat)" />
                        }
                    }
                </div>
            </div>
        }
        else
        {
            <div class="col-12 row justify-content-center align-items-center text-center" style="background: url('/images/box.png')  no-repeat; background-size: 100% 100%; width: 380px; height:650px">
                <div class="row justify-content-around align-items-center" style="margin-top: 220px; height: 430px;">
                    @foreach (int i in DrawerNos)
                    {
                        <RadzenButton class="col-12" Click="@(() => SelectDrawer(i))" Text="@i.ToString()" Disabled="@(status > 0)" Shade="Shade.Light" Variant="@(drawerNo !=i ? Variant.Outlined : Variant.Flat)" />

                    }
                </div>
            </div>
        }
    </div>
    <RadzenDataGrid @ref="grid" Style="overflow:auto"
                    LoadData="@LoadData"
                    IsLoading="@isLoading"
                    Count="@count"
                    EmptyText="无数据"
                    Data="@channels"
                    AllowColumnResize="true" AllowAlternatingRows="false"
                    CellClick="@((DataGridCellMouseEventArgs<ChannelStock> args) => OnCellClick(args))"
                    AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
        <HeaderTemplate>
            <RadzenRow JustifyContent="JustifyContent.End">
                @if (status < 3)
                {
                    <RadzenButton IsBusy="@(status>0)" BusyText="加药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Light" Text="加药" Click="@OpenDrawer" />
                }
                @if (status == 3)
                {
                    <RadzenButton Visible="@CompleteIsEnable" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Light" Text="完成" Click="@AddFinish" />
                }
                @if (status > 0 && status <= 3)
                {
                    <RadzenButton Visible="@CancleIsEnable" Variant="Variant.Flat" Text="取消" Click="@Cancel" Style="width: 120px" />
                }
            </RadzenRow>
        </HeaderTemplate>
        <Columns>
            <RadzenDataGridColumn Width="70px" Title="库位" Property="ColNo"></RadzenDataGridColumn>
            <RadzenDataGridColumn Width="130px" Title="药品名称" Property="Drug.DrugName">
                <Template Context="channel">
                    <RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.Drug?.DrugName</RadzenText>
                    <RadzenText TextStyle="TextStyle.Caption">@channel.Drug?.DrugSpec</RadzenText>
                </Template>
            </RadzenDataGridColumn>
            <RadzenDataGridColumn Width="110px" Title="批次" Property="ManuNo">
                <Template Context="channel">
                    <RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.drugManuNo?.ManuNo</RadzenText>

                    @if (channel.drugManuNo != null && channel.drugManuNo.EffDate.ToString().Length > 10)
                    {
                        <RadzenText TextStyle="TextStyle.Caption">
                            @channel.drugManuNo.EffDate.ToString().Substring(0, 10)
                        </RadzenText>
                    }
                    else
                    {
                        <RadzenText TextStyle="TextStyle.Caption">
                            @channel.drugManuNo?.EffDate
                        </RadzenText>
                    }
                </Template>
                <EditTemplate Context="channel">

                    @if (channel.Quantity == 0 && !String.IsNullOrEmpty(channel.DrugId))
                    {
                        <RadzenDropDown TValue="DrugManuNo" Name="ManuNo" @bind-Value="channel.drugManuNo" Data="@channel.Drug?.Manus" Style="width:100%; display: block;">
                            <Template>
                                <RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@((context as DrugManuNo)?.ManuNo)</RadzenText>
                                @if ((context as DrugManuNo).EffDate != null && (context as DrugManuNo).EffDate.ToString().Length > 10)
                                {

                                    <RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo).EffDate.ToString().Substring(0, 10))</RadzenText>
                                }
                                else
                                {

                                    <RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo)?.EffDate)</RadzenText>
                                }
                            </Template>
                            <ValueTemplate>
                                <RadzenStack Orientation="Orientation.Horizontal">
                                    <RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@((context as DrugManuNo)?.ManuNo)</RadzenText>
                                    @if ((context as DrugManuNo).EffDate != null && (context as DrugManuNo).EffDate.ToString().Length > 10)
                                    {

                                        <RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo).EffDate.ToString().Substring(0, 10))</RadzenText>
                                    }
                                    else
                                    {

                                        <RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo)?.EffDate)</RadzenText>
                                    }
                                </RadzenStack>
                            </ValueTemplate>
                        </RadzenDropDown>
                        <RadzenRequiredValidator Text="请选择批次" Component="ManuNo" Popup="true" />
                    }
                    else
                    {

                        <RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.drugManuNo?.ManuNo</RadzenText>
                        <RadzenText TextStyle="TextStyle.Caption">@channel.drugManuNo?.EffDate</RadzenText>
                    }
                </EditTemplate>
            </RadzenDataGridColumn>
            <RadzenDataGridColumn Title="库存" Width="60px" Property="Quantity">
                <Template Context="cs">
                    <RadzenButton ButtonStyle="ButtonStyle.Info" Variant="Variant.Flat" Shade="Shade.Lighter" class="m-1" Text="@cs.Quantity.ToString()" />
                </Template>
            </RadzenDataGridColumn>
            <RadzenDataGridColumn MinWidth="100px" Title="加药数量" Property="AddQuantity">
                <EditTemplate Context="cs">
                    @if (cs.BoardType.ToString().Contains("2") || cs.BoardType.ToString().Contains("3"))
                    {
                        @cs.AddQuantity
                    }
                    else
                    {
                        <RadzenNumeric Min="0" Style="display: block" Name="Quantity" @bind-Value=@cs.AddQuantity />
                        <RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" Text="请填写正确的添加数量" Component="Quantity" Popup="true" />
                    }
                </EditTemplate>
            </RadzenDataGridColumn>
        </Columns>
    </RadzenDataGrid>

</RadzenStack>
@code {
    @inject IChannelListDao channelListDao;
    @inject NavigationManager na;
    @inject PortUtil PortUtil;
    @inject NotificationService _message
    @inject IOptions<DrawerConfig> setting;
    int status = 0;
    int drawerNo = 1;
    RadzenDataGrid<ChannelStock> grid;
    private List<ChannelStock>? channels;
    bool isLoading;
    int count;
    int[] DrawerNos = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
    int[] BeforeQuantity = new int[9];
    int[] AfterQuantity = new int[9];
    private readonly ILog logger = LogManager.GetLogger(typeof(DrawerAdd));

    // 当前操作的库位号列表
    public List<int> ColNos { get; set; } = new List<int>();
    int currentCol = 0;
    bool CompleteIsEnable = true;
    bool CancleIsEnable = true;
    async Task LoadData(LoadDataArgs args)
    {
        isLoading = true;

        var result = await channelListDao.GetChannelStockByDrawerNoWithDrawers(drawerNo);
        // var result = await channelListDao.GetChannelStockByDrawerNo(drawerNo);
        // Update the Data property
        DrawerNos = result.DrawerArray;
        channels = result.ChannelStocks;
        // Update the count
        count = result.ChannelStocks.Count;


        isLoading = false;
    }
    async Task OpenDrawer()
    {
        PortUtil.DrawerNo = this.drawerNo;
        this.status = 1;
        // 根据抽屉类型来决定打开前是否需要查询数量
        var promiseUtil = new PromiseUtil<object>();
        await promiseUtil.taskAsyncLoop(500, null, async (data, next, stop) =>
        {
            try
            {
                if (this.status == 0)
                {
                    stop();
                }
                // 开启抽屉
                else if (this.status == 1)
                {
                    // 判断是否为单支抽屉
                    if (setting.Value.single != null && setting.Value.single.Contains(this.drawerNo))
                    {
                        byte[] quantity = await PortUtil.CheckQuantityByDrawer(this.drawerNo);
                        BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
                        logger.Info($"单支抽屉，开抽屉前检测数量【{string.Join(",", BeforeQuantity)}】");
                    }
                    // 判断是否为称重抽屉
                    // if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
                    // {
                    //     //开抽屉前先查数
                    //     for (int i = 0; i < 9; i++)
                    //     {
                    //         int beforeQuantity = await PortUtil.CheckQuantityForSingle(i + 1);
                    //         BeforeQuantity[i] = beforeQuantity;
                    //         logger.Info($"BeforeQuantity:{i++}-{beforeQuantity}数量{string.Join(",", BeforeQuantity)}");
                    //     }
                    // }

                    var b = await PortUtil.OpenDrawerStatus(this.drawerNo);
                    if (b)
                    {
                        PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
                        PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开，请，加药");
                        this.status = 2;
                        PortUtil.Operate = true;
                        next();
                    }
                    else
                    {
                        _message.Notify(
                            new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败，请检测硬件", Duration = 4000 }
                        );
                        logger.Info($"抽屉打开失败");
                        RestData();
                        PortUtil.Operate = false;
                        stop();
                    }

                }
                // 检测状态
                else if (this.status == 2)
                {
                    // 查询抽屉是否为关闭状态
                    var b = await PortUtil.CheckDrawerStatus2(drawerNo);
                    // 关闭则改变状态并终止循环
                    if (b)
                    {
                        PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
                        PortUtil.SpeakAsync($"加药完成，请，核对，或，录入，正确的，添加数量");
                        // 判断是否为称重抽屉
                        if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
                        {
                            //关闭抽屉后获取称重稳定数量
                            await GetWeightQuantity();
                        }
                        this.status = 3;
                        PortUtil.Operate = false;
                        stop();
                    }
                    else
                    {
                        //药盒抽屉，开药盒
                        if (setting.Value.box != null && setting.Value.box.Contains(this.drawerNo))
                        {
                            if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
                            {
                                if (currentCol > 0)
                                {
                                    //开药盒前先查数
                                    int beforeQuantity = await PortUtil.CheckQuantityForSingle(currentCol);
                                    BeforeQuantity[currentCol - 1] = beforeQuantity;
                                    logger.Info($"BeforeQuantity:{currentCol}-{beforeQuantity}数量{string.Join(",", BeforeQuantity)}");
                                    await Task.Delay(200);
                                    ColNos.Add(currentCol);
                                }
                            }
                            //药盒抽屉，开药盒
                            if (currentCol > 0)
                            {
                                await PortUtil.OpenBoxByColNo(currentCol);
                            }
                            currentCol = 0;
                        }

                        if (setting.Value.single != null && setting.Value.single.Contains(this.drawerNo))
                        {
                            byte[] quantity = await PortUtil.CheckQuantityByDrawer(this.drawerNo);
                            AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
                            logger.Info($"单支抽屉，抽屉未关检测数量【{string.Join(",", AfterQuantity)}】");

                            channels.ForEach(cl =>
                            {
                                cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
                            });
                            await InvokeAsync(StateHasChanged);
                        }
                        // 判断是否为称重抽屉
                        if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
                        {
                            //开抽屉后查数
                            for (int i = 0; i < ColNos.Count; i++)
                            {
                                int afterQuantity = await PortUtil.CheckQuantityForSingle(ColNos[i]);
                                AfterQuantity[ColNos[i] - 1] = afterQuantity;
                                logger.Info($"AfterQuantity:{ColNos[i]}-{string.Join(",", AfterQuantity)}数量{string.Join(", ", BeforeQuantity)}");
                            }
                            channels.Where(cl => ColNos.Contains(cl.ColNo)).ToList().ForEach(cl =>
                              {
                                  cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
                              });
                            await InvokeAsync(StateHasChanged);
                        }
                        next(); // continue iteration
                    }

                }
            }
            catch (Exception e)
            {
                logger.Info($"抽屉加药发生错误，{e.Message}");
                _message.Notify(
                    new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误，{e.Message}", Duration = 4000 }
                );
                if (setting.Value.single != null && setting.Value.single.Contains(this.drawerNo))
                {
                    PortUtil.AllLightOff();
                }
                RestData();
                stop();
            }
        });
    }

    void RestData()
    {
        PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
        this.status = 0;
        this.BeforeQuantity = new int[9];
        this.AfterQuantity = new int[9];
        currentCol = 0;
        ColNos.Clear();
    }
    //关闭抽屉后获取称重稳定数量
    public async Task GetWeightQuantity()
    {
        List<int[]> finallyQuantity = new List<int[]>();
        await new PromiseUtil<int>().taskAsyncLoop(200, 0, async (options, next, stop) =>
            {
                if (!PortUtil.Operate || this.status == 0)
                {
                    stop();
                }
                else
                {
                    try
                    {
                        logger.Info("关闭抽屉后获取称重稳定数量");
                        if (finallyQuantity.Count >= 10)
                        {
                            for (int i = 0; i < finallyQuantity.Count; i++)
                            {
                                logger.Info($"finallyQuantity{i} {string.Join(",", finallyQuantity[i])}");
                            }
                            if (AreAllArraysEqual(finallyQuantity))
                            {
                                stop();
                                channels.ForEach(cl =>
                                 {
                                     cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
                                 });
                                CompleteIsEnable = true;
                                CancleIsEnable = true;
                                logger.Info("对比成功停止循环");
                                await InvokeAsync(StateHasChanged);
                            }
                            else
                            {
                                finallyQuantity.RemoveAt(0);
                                next();
                            }
                        }
                        else
                        {
                            if (finallyQuantity.Count >= 9)
                            {
                                CancleIsEnable = true;
                            }
                            else
                            {
                                CancleIsEnable = false;
                            }
                            CompleteIsEnable = false;
                            PortUtil.DrawerNo = drawerNo;
                            PortUtil.ColNoLst = ColNos;
                            int[] quantity = await PortUtil.CheckQuantityByAddrForMulti();
                            AfterQuantity = quantity;
                            int[] Quantitys = new int[BeforeQuantity.Length];
                            for (int i = 0; i < BeforeQuantity.Length; i++)
                            {
                                Quantitys[i] = BeforeQuantity[i] - AfterQuantity[i];
                            }
                            finallyQuantity.Add(Quantitys);
                            logger.Info($"Quantity{string.Join(",", Quantitys)}");

                            channels.ForEach(cl =>
                            {
                                cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
                            });
                            next();
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.Info($"关闭抽屉后获取称重稳定数量异常{ex.Message}");
                        next();
                    }
                }
            });
    }
    public bool AreAllArraysEqual(List<int[]> arrays)
    {
        if (arrays == null || arrays.Count == 0) return false;
        // 取第一个数组作为参照进行比较
        var referenceArray = arrays[0];
        // 检查列表中除了第一个数组外的所有数组是否与第一个数组相等
        return arrays.Skip(1).All(array => array.SequenceEqual(referenceArray));
    }
    async Task AddFinish()
    {
        if (channels.Any(cl => cl.AddQuantity != 0 && cl.DrugId != null && cl.drugManuNo != null))
        {
            // 保存账册、操作记录
            var b = await channelListDao.DrawerOperationFinish(channels.Where(cl => cl.AddQuantity != 0).ToList(), 1);
            if (!b)
            {
                _message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
                logger.Error($"抽屉加药保存数据库失败，数据{JsonConvert.SerializeObject(channels)}");
            }
            else
            {
                // 判断是否为标签抽屉
                if (setting.Value != null && setting.Value.label != null && setting.Value.label.Contains(this.drawerNo))
                {
                    //写标签数量
                    channels.Where(it => it.AddQuantity > 0).ToList().ForEach(async it =>
                    {
                        await PortUtil.WriteQuantityMethod(it.Quantity + it.AddQuantity, it.DrawerNo, it.ColNo);
                    });
                }
                ColNos.Clear();
            }
        }

        //重置状态
        this.RestData();
        // 重新查询库存
        await grid.Reload();
    }

    void Cancel()
    {
        RestData();
    }

    void SelectDrawer(int drawerNo)
    {
        this.drawerNo = drawerNo;
        grid.Reload();
    }

    void OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args)
    {
        // if (args.Data.BoardType.ToString().Contains("3"))
        // {
        //     //是药盒抽屉则点击行，打开对应行的药盒
        //     if (!ColNos.Contains(args.Data.ColNo))
        //     {
        //         ColNos.Add(args.Data.ColNo);
        //     }
        // }
        if (setting.Value.box.Contains(args.Data.DrawerNo) && status != 2)
        {
            PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
            PortUtil.SpeakAsync("请先点取药按钮打开抽屉");
        }
        currentCol = args.Data.ColNo;
        grid.EditRow(args.Data);
    }
    private IDisposable? registration;
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            registration = na.RegisterLocationChangingHandler(OnLocationChanging);
        }
    }

    private ValueTask OnLocationChanging(LocationChangingContext context)
    {
        // 操作中不可跳转页面
        if (status > 0)
        {
            context.PreventNavigation(); //阻止导航
        }
        return ValueTask.CompletedTask;
    }
    //在生命周期函数Dispose中，移除订阅的事件，并销毁非托管资源registration===========================================
    public void Dispose()
    {
        registration?.Dispose();
    }
}
