@layout Layout.HMILayout
@page "/sehc/da3/line1"

@using Microsoft.AspNetCore.SignalR.Client
@using RobotNet.Script.Shares
@using RobotNet.WebApp.Clients

@attribute [Authorize]
@implements IAsyncDisposable

@inject HMIHubClient hmiClient
@inject ISnackbar Snackbar
@inject IDialogService Dialog

<div class="w-100 h-100 position-relative overflow-hidden">
    <div class="w-100 h-100 position-absolute top-0 start-0 overflow-hidden d-flex flex-row">
        <div class="h-100 d-flex flex-column justify-content-start align-items-center p-2" style="width: 10%; border-right: 2px solid #34495e;">
            <!-- Card thông tin số nhiệm vụ - HMI Industrial Style -->
            <div class="mb-3 w-100 user-select-none position-relative" @onclick="CallResetStep" style="
                    background: linear-gradient(145deg, #34495e, #2c3e50);
                    border: 2px solid #7f8c8d;
                    border-radius: 8px;
                    box-shadow:
                        inset 0 2px 4px rgba(255, 255, 255, 0.1),
                        0 4px 8px rgba(0, 0, 0, 0.3);
                    color: #ecf0f1;
                    font-family: 'Courier New', monospace;
                ">
                <div class="text-center py-2" style="
                        background: linear-gradient(145deg, #3498db, #2980b9);
                        border-bottom: 1px solid #34495e;
                        border-radius: 6px 6px 0 0;
                        font-size: 18px;
                        font-weight: bold;
                        text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
                        color: white;
                    ">
                    STEP NUMBER
                </div>
                <div class="text-center py-3" style="
                        background: linear-gradient(145deg, #1a252f, #16202b);
                        border-radius: 0 0 6px 6px;
                    ">
                    <div style="
                            font-size: 48px;
                            font-weight: bold;
                            color: #00ff00;
                            text-shadow: 0 0 8px #00ff00;
                            font-family: 'Courier New', monospace;
                            letter-spacing: 2px;
                        ">
                        @Line1_HMI_Model.SEHCMissionStep
                    </div>
                </div>
                <MudOverlay Visible="Line1_HMI_Model.Request_Reset_SEHC_DA3_Line1" DarkBackground AutoClose="false" Absolute>
                    <div class="d-flex flex-column justify-content-center">
                        <div class="d-flex justify-content-center">
                            <MudProgressCircular Color="Color.Secondary" Size="Size.Large" Indeterminate="true" />
                        </div>
                    </div>
                </MudOverlay>
            </div>

            <button class="mb-3 w-100 hmi-button onoff @hmiBtnIsWorkingClass">
                WORKING @(Line1_HMI_Model.IsWorking ? "ON" : "OFF")
            </button>

            <button class="mb-3 w-100 hmi-button onoff @hmiBtnHasEmptyTrolleyClass" @onclick="ToggleHasEmptyTrolley">
                EMPTY TROLLEY @(Line1_HMI_Model.Has_Empty_Trolley ? "ON" : "OFF")
            </button>

            <button class="mb-3 w-100 hmi-button onoff @hmiBtnGoHomeClass" @onclick="ToggleGoHome">
                GO HOME
            </button>

            <!-- Image Trolley - Full Width -->
            <div class="mb-3 w-100" @onclick="ToggleHasFullTrolley">
                <img src="sehc/trolley.png" class="@trolleyFullClass" alt="Trolley" style="
                        width: 100%;
                        height: auto;
                        object-fit: cover;
                    ">
            </div>
        </div>

        <div class="h-100 d-flex flex-column" style="width: 45%; overflow: hidden; border-left: 1px solid red;">
            <div class="d-flex flex-row justify-content-between align-items-center gap-3 p-3" style="height: 15%;">
                <button class="hmi-button start @hmiBtnEnAutoAClass" @onclick="ToggleAutoManualA">@(Line1_HMI_Model.EnableAutoA ? "AUTO" : "MANUAL")</button>
                <button class="hmi-button request @hmiBtnInAClass" @onclick="ToggleReqInA">REQ IN A<br>@(Line1_HMI_Model.Req_In_A ? "ON" : "OFF")</button>
                <button class="hmi-button request @hmiBtnInBesideAClass" @onclick="ToggleReqInBesideA">REQ IN BESIDE A<br>@(Line1_HMI_Model.Req_In_Beside_A ? "ON" : "OFF")</button>
                <button class="hmi-button close @hmiBtnCloseAClass" @onclick="ToggleReqCloseCylenderA">REQ CLOSE A<br>@(Line1_HMI_Model.Req_Close_Cylinder_A ? "ON" : "OFF")</button>
            </div>

            <div class="w-100 d-flex flex-row" style="height: 85%;">
                <div class="h-100 d-flex flex-grow-1" style="position: relative;">
                    <img src="sehc/amr.png" class="@amrReadyUndockAClass" style="height: calc(75% * 0.25); width: auto; object-fit: contain; position: absolute; right: 0%; top: 40%;" />
                </div>

                <div class="h-100 d-flex flex-column" style="width: auto;">
                    <div style="height: 90%; position: relative;">
                        <div class="access-status @accessInAClass"
                             style="position: absolute; width: 80%; height: 2%; left: 10%; bottom: -2%; border-radius: 3px; display: flex; align-items: center; justify-content: center; color: white; font-size: 16px; font-weight: bold;">
                        </div>
                        <div class="access-status @accessInBesideAClass"
                             style="position: absolute; width: 3%; height: 70%; left: 5%; top: 19%; border-radius: 3px; display: flex; align-items: center; justify-content: center; color: white; font-size: 16px; font-weight: bold;">
                        </div>
                        <img src="sehc/station.png" style="height: 100%; width: auto; object-fit: contain;" />
                        <img src="sehc/amr.png" class="@amrInAClass" style="position: absolute; transform: rotate(90deg); top: 37%; left: 21.5%; width: 60%; height: 30%; object-fit: contain;" />
                        <img src="sehc/trolley.png" class="@trolleyAClass" style="position: absolute; top: 5.5%; right: 1%; width: 95%; height: 95%; object-fit: contain;" />
                        <div class="@cylinderStateAClass" style="position: absolute; top: 10%; left: 12.5%;"></div>
                        <div class="@cylinderStateAClass" style="position: absolute; top: 90%; left: 12.5%;"></div>
                    </div>

                    <div class="d-flex align-items-center justify-content-center" style="height: 10%;">
                        <div id="station-left-indicator" class="station-indicator @indicatorAClass">
                            <div class="direction-track">
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="center-dot"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="h-100 d-flex flex-column" style="width: 45%; overflow: hidden; border-left: 1px solid red;">
            <div class="d-flex flex-row-reverse justify-content-between align-items-center gap-3 p-3" style="height: 15%;">
                <button class="hmi-button start @hmiBtnEnAutoBClass" @onclick="ToggleAutoManualB">@(Line1_HMI_Model.EnableAutoB ? "AUTO" : "MANUAL")</button>
                <button class="hmi-button request @hmiBtnInBClass" @onclick="ToggleReqInB"> REQ IN B<br>@(Line1_HMI_Model.Req_In_B ? "ON" : "OFF")</button>
                <button class="hmi-button request @hmiBtnInBesideBClass" @onclick="ToggleReqInBesideB"> REQ IN BESIDE B<br>@(Line1_HMI_Model.Req_In_Beside_B ? "ON" : "OFF")</button>
                <button class="hmi-button close @hmiBtnCloseBClass" @onclick="ToggleReqCloseCylenderB">REQ CLOSE B<br>@(Line1_HMI_Model.Req_Close_Cylinder_B ? "ON" : "OFF")</button>
            </div>

            <div class="w-100 d-flex flex-row-reverse" style="height: 85%;">
                <div class="h-100 d-flex flex-grow-1" style="position: relative;">
                    <img src="sehc/amr.png" class="@amrReadyUndockBClass" style="transform: rotate(180deg); height: calc(75% * 0.25); width: auto; object-fit: contain; position: absolute; left: 0%; top: 40%;" />
                </div>

                <div class="h-100 d-flex flex-column" style="width: auto;">
                    <div style="height: 90%; position: relative;">
                        <div class="access-status @accessInBClass"
                             style="position: absolute; width: 80%; height: 2%; left: 10%; bottom: -2%; border-radius: 3px; display: flex; align-items: center; justify-content: center; color: white; font-size: 16px; font-weight: bold;">
                        </div>
                        <div class="access-status @accessInBesideBClass"
                             style="position: absolute; width: 3%; height: 70%; right: 5%; top: 19%; border-radius: 3px; display: flex; align-items: center; justify-content: center; color: white; font-size: 16px; font-weight: bold;">
                        </div>
                        <img src="sehc/station.png" style="transform: scaleX(-1); height: 100%; width: auto; object-fit: contain;" />
                        <img src="sehc/amr.png" class="@amrInBClass" style="position: absolute; transform: rotate(90deg); top: 37%; right: 21.5%; width: 60%; height: 30%; object-fit: contain;" />
                        <img src="sehc/trolley.png" class="@trolleyBClass" style="position: absolute; top: 5.5%; left: 1%; width: 95%; height: 95%; object-fit: contain;" />
                        <div class="@cylinderStateBClass" style="position: absolute; top: 10%; right: 12.5%;"></div>
                        <div class="@cylinderStateBClass" style="position: absolute; top: 90%; right: 12.5%;"></div>
                    </div>

                    <div style="height: 10%;">
                        <div id="station-right-indicator" class="station-indicator @indicatorBClass">
                            <div class="direction-track">
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="arrow-flow"></div>
                                <div class="center-dot"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<MudOverlay Visible="DisableControl" DarkBackground AutoClose="false">
    <div class="d-flex flex-column justify-content-center">
        <div class="d-flex justify-content-center">
            <MudProgressCircular Color="Color.Secondary" Size="Size.Large" Indeterminate="true" />
        </div>
        <div>
            <MudText Typo="Typo.h3">CONNECTING ...</MudText>
        </div>
    </div>
</MudOverlay>

<MudOverlay Visible="DisableProcess" DarkBackground AutoClose="false">
    <div class="d-flex flex-column justify-content-center">
        <div class="d-flex justify-content-center">
            <MudProgressCircular Color="Color.Secondary" Size="Size.Large" Indeterminate="true" />
        </div>
        <div>
            <MudText Typo="Typo.h3">WAIT FOR RUNNING ...</MudText>
        </div>
    </div>
</MudOverlay>

@code {
    private bool DisableControl = true;
    private bool DisableProcess => !DisableControl && processorState != ProcessorState.Running;
    private ProcessorState processorState = ProcessorState.Idle;

    private string hmiBtnResetStepClass => $"{(Line1_HMI_Model.Request_Reset_SEHC_DA3_Line1 ? "inactive" : "")}";
    private string hmiBtnIsWorkingClass => $"{(Line1_HMI_Model.IsWorking ? "" : "inactive")}"; 
    private string hmiBtnHasEmptyTrolleyClass => $"{(Line1_HMI_Model.Has_Empty_Trolley ? "" : "inactive")}";
    private string hmiBtnGoHomeClass => $"{(Line1_HMI_Model.Request_GoHome ? "inactive" : "")}";

    private string hmiBtnEnAutoAClass => $"{(Line1_HMI_Model.EnableAutoA ? "" : "off")}";
    private string hmiBtnInAClass => $"{(Line1_HMI_Model.EnableAutoA ? "inactive" : "")} {(Line1_HMI_Model.Req_In_A ? "" : "off")}";
    private string hmiBtnInBesideAClass => $"{(Line1_HMI_Model.EnableAutoA ? "inactive" : "")} {(Line1_HMI_Model.Req_In_Beside_A ? "" : "off")}";
    private string hmiBtnCloseAClass => $"{(Line1_HMI_Model.EnableAutoA ? "inactive" : "")} {(Line1_HMI_Model.Req_Close_Cylinder_A ? "" : "off")}";

    private string hmiBtnEnAutoBClass => $"{(Line1_HMI_Model.EnableAutoB ? "" : "off")}"; 
    private string hmiBtnInBClass => $"{(Line1_HMI_Model.EnableAutoB ? "inactive" : "")} {(Line1_HMI_Model.Req_In_B ? "" : "off")}";
    private string hmiBtnInBesideBClass => $"{(Line1_HMI_Model.EnableAutoB ? "inactive" : "")} {(Line1_HMI_Model.Req_In_Beside_B ? "" : "off")}";
    private string hmiBtnCloseBClass => $"{(Line1_HMI_Model.EnableAutoB ? "inactive" : "")} {(Line1_HMI_Model.Req_Close_Cylinder_B ? "" : "off")}";

    private string cylinderStateAClass => $"{(Line1_HMI_Model.Cylinder_Opened_A ? "" : "led-indicator")}";
    private string cylinderStateBClass => $"{(Line1_HMI_Model.Cylinder_Opened_B ? "" : "led-indicator")}";

    private string trolleyAClass => $"{(Line1_HMI_Model.Empty_A ? "trolley-inactive" : "")}";
    private string trolleyBClass => $"{(Line1_HMI_Model.Empty_B ? "trolley-inactive" : "")}";
    private string trolleyFullClass => $"{(Line1_HMI_Model.AGV_Push_Noti_Mem ? "" : "trolley-inactive")}";

    private string indicatorAClass => GetIndicatorAClass();
    private string indicatorBClass => GetIndicatorBClass();

    private string amrReadyUndockAClass => $"{(Line1_HMI_Model.AMR_Ready_Undock_A ? "" : "image-inactive")}";
    private string amrReadyUndockBClass => $"{(Line1_HMI_Model.AMR_Ready_Undock_B ? "" : "image-inactive")}";

    private string amrInAClass => $"{(Line1_HMI_Model.AMR_In_Station_A ? "" : "image-inactive")}";
    private string amrInBClass => $"{(Line1_HMI_Model.AMR_In_Station_B ? "" : "image-inactive")}";
    
    private string accessInAClass => Line1_HMI_Model.Access_In_A ? "access-allowed" : "access-denied";
    private string accessInBClass => Line1_HMI_Model.Access_In_B ? "access-allowed" : "access-denied";
    private string accessInBesideAClass => Line1_HMI_Model.Access_In_Beside_A ? "access-allowed" : "access-denied";
    private string accessInBesideBClass => Line1_HMI_Model.Access_In_Beside_B ? "access-allowed" : "access-denied";

    private SEHC_DA3_Line1_HMI_Model Line1_HMI_Model;

    IDictionary<string, string> SyncVariables = new Dictionary<string, string>()
    {
        {nameof(SEHC_DA3_Line1_HMI_Model.IsWorking), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.SEHCMissionStep), "-1" },
        {nameof(SEHC_DA3_Line1_HMI_Model.EnableAutoA), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.EnableAutoB), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Request_Reset_SEHC_DA3_Line1), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.AMR_In_Station_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.AMR_In_Station_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.AMR_Ready_Undock_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.AMR_Ready_Undock_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Req_In_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Req_In_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Req_In_Beside_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Req_In_Beside_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Req_Close_Cylinder_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Req_Close_Cylinder_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Robot_Working_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Robot_Working_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Empty_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Empty_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Cylinder_Opened_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Cylinder_Opened_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Access_In_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Access_In_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Access_In_Beside_A), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Access_In_Beside_B), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.AGV_Push_Noti_Mem), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Has_Empty_Trolley), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.MoveTrolleyInStationA), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.MoveTrolleyInStationB), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.MoveTrolleyOutStationA), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.MoveTrolleyOutStationB), bool.FalseString },
        {nameof(SEHC_DA3_Line1_HMI_Model.Request_GoHome), bool.FalseString },
    };

    System.Timers.Timer timer = new System.Timers.Timer(300)
    {
        AutoReset = true,
    };

    protected override async Task OnInitializedAsync()
    {
        timer.Elapsed += OnTimerElapsed;

        hmiClient.ConnectionStateChanged += OnConnectionStateChanged;
        hmiClient.StateChanged += OnProcessStateChanged;

        await hmiClient.StartAsync();

        timer.Start();
        OnProcessStateChanged(await hmiClient.GetState());

        await base.OnInitializedAsync();
    }

    void OnConnectionStateChanged(HubConnectionState state)
    {
        Console.WriteLine($"HubConnectionState={state}");
        DisableControl = state != HubConnectionState.Connected;
        StateHasChanged();
    }

    void OnProcessStateChanged(ProcessorState state)
    {
        processorState = state;
        if (state == ProcessorState.Running)
        {
            if (!timer.Enabled)
            {
                timer.Start();
            }
        }
        else if (timer.Enabled)
        {
            timer.Stop();
        }
        StateHasChanged();
    }

    void OnTimerElapsed(object? sender, System.Timers.ElapsedEventArgs e)
    {
        InvokeAsync(async Task () =>
        {
            var variables = await hmiClient.GetVariables(SyncVariables.Keys);
            foreach (var key in variables.Keys)
            {
                SyncVariables[key] = variables[key];
            }

            Line1_HMI_Model.IsWorking = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.IsWorking)]);
            Line1_HMI_Model.SEHCMissionStep = int.TryParse(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.SEHCMissionStep)], out int step) ? step : -1;
            Line1_HMI_Model.EnableAutoA = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.EnableAutoA)]);
            Line1_HMI_Model.EnableAutoB = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.EnableAutoB)]);
            Line1_HMI_Model.Request_Reset_SEHC_DA3_Line1 = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Request_Reset_SEHC_DA3_Line1)]);
            Line1_HMI_Model.AMR_In_Station_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.AMR_In_Station_A)]);
            Line1_HMI_Model.AMR_In_Station_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.AMR_In_Station_B)]);
            Line1_HMI_Model.AMR_Ready_Undock_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.AMR_Ready_Undock_A)]);
            Line1_HMI_Model.AMR_Ready_Undock_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.AMR_Ready_Undock_B)]);
            Line1_HMI_Model.Req_In_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Req_In_A)]);
            Line1_HMI_Model.Req_In_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Req_In_B)]);
            Line1_HMI_Model.Req_In_Beside_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Req_In_Beside_A)]);
            Line1_HMI_Model.Req_In_Beside_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Req_In_Beside_B)]);
            Line1_HMI_Model.Req_Close_Cylinder_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Req_Close_Cylinder_A)]);
            Line1_HMI_Model.Req_Close_Cylinder_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Req_Close_Cylinder_B)]);
            Line1_HMI_Model.Robot_Working_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Robot_Working_A)]);
            Line1_HMI_Model.Robot_Working_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Robot_Working_B)]);
            Line1_HMI_Model.Empty_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Empty_A)]);
            Line1_HMI_Model.Empty_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Empty_B)]);
            Line1_HMI_Model.Cylinder_Opened_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Cylinder_Opened_A)]);
            Line1_HMI_Model.Cylinder_Opened_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Cylinder_Opened_B)]);
            Line1_HMI_Model.Access_In_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Access_In_A)]);
            Line1_HMI_Model.Access_In_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Access_In_B)]);
            Line1_HMI_Model.Access_In_Beside_A = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Access_In_Beside_A)]);
            Line1_HMI_Model.Access_In_Beside_B = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Access_In_Beside_B)]);
            Line1_HMI_Model.AGV_Push_Noti_Mem = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.AGV_Push_Noti_Mem)]);
            Line1_HMI_Model.Has_Empty_Trolley = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Has_Empty_Trolley)]);
            Line1_HMI_Model.MoveTrolleyInStationA = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.MoveTrolleyInStationA)]);
            Line1_HMI_Model.MoveTrolleyInStationB = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.MoveTrolleyInStationB)]);
            Line1_HMI_Model.MoveTrolleyOutStationA = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.MoveTrolleyOutStationA)]);
            Line1_HMI_Model.MoveTrolleyOutStationB = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.MoveTrolleyOutStationB)]);
            Line1_HMI_Model.Request_GoHome = bool.TrueString.Equals(SyncVariables[nameof(SEHC_DA3_Line1_HMI_Model.Request_GoHome)]);
            StateHasChanged();
        }).ConfigureAwait(false);
    }

    string GetIndicatorAClass()
    {
        if (Line1_HMI_Model.Robot_Working_A) return "working";

        if (Line1_HMI_Model.IsWorking)
        {
            if (Line1_HMI_Model.MoveTrolleyOutStationA)
            {
                return "request-out";
            }
            else if (Line1_HMI_Model.MoveTrolleyInStationA)
            {
                return "request-in";
            }
            else
            {
                return "standby";
            }
        }
        else
        {
            return "hidden";
        }
    }

    string GetIndicatorBClass()
    {
        if (Line1_HMI_Model.Robot_Working_B) return "working";

        if (Line1_HMI_Model.IsWorking)
        {
            if (Line1_HMI_Model.MoveTrolleyOutStationB)
            {
                return "request-out";
            }
            else if (Line1_HMI_Model.MoveTrolleyInStationB)
            {
                return "request-in";
            }
            else
            {
                return "standby";
            }
        }
        else
        {
            return "hidden";
        }
    }

    async Task ToggleAutoManualA()
    {
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.EnableAutoA), Line1_HMI_Model.EnableAutoA ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }
    async Task ToggleAutoManualB()
    {
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.EnableAutoB), Line1_HMI_Model.EnableAutoB ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }

    async Task ToggleReqInA()
    {
        if (Line1_HMI_Model.EnableAutoA) return;
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Req_In_A), Line1_HMI_Model.Req_In_A ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }

    async Task ToggleReqInBesideA()
    {
        if (Line1_HMI_Model.EnableAutoA) return;
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Req_In_Beside_A), Line1_HMI_Model.Req_In_Beside_A ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }

    async Task ToggleReqCloseCylenderA()
    {
        if (Line1_HMI_Model.EnableAutoA) return;
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Req_Close_Cylinder_A), Line1_HMI_Model.Req_Close_Cylinder_A ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }

    async Task ToggleReqInB()
    {
        if (Line1_HMI_Model.EnableAutoB) return;
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Req_In_B), Line1_HMI_Model.Req_In_B ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }

    async Task ToggleReqInBesideB()
    {
        if (Line1_HMI_Model.EnableAutoB) return;
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Req_In_Beside_B), Line1_HMI_Model.Req_In_Beside_B ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }

    async Task ToggleReqCloseCylenderB()
    {
        if (Line1_HMI_Model.EnableAutoB) return;
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Req_Close_Cylinder_B), Line1_HMI_Model.Req_Close_Cylinder_B ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }
    
    async Task ToggleHasEmptyTrolley()
    {
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Has_Empty_Trolley), Line1_HMI_Model.Has_Empty_Trolley ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }

    async Task ToggleGoHome()
    {
        if (Line1_HMI_Model.Request_GoHome) return;

        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Request_GoHome), bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }
    
    async Task ToggleHasFullTrolley()
    {
        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.AGV_Push_Noti_Mem), Line1_HMI_Model.AGV_Push_Noti_Mem ? bool.FalseString : bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }
    async Task CallResetStep()
    {
        if (Line1_HMI_Model.Request_Reset_SEHC_DA3_Line1) return;
        bool? confirm = await Dialog.ShowMessageBox(
            "Reset Mission State",
            "Hãy xác nhận đặt lại trạng thái hoạt động!",
            yesText: "Yes", cancelText: "Cancel");

        if (confirm != true) return;

        var result = await hmiClient.SetVariable(nameof(SEHC_DA3_Line1_HMI_Model.Request_Reset_SEHC_DA3_Line1), bool.TrueString);
        if (result == null)
        {
            Snackbar.Add("HMI client SetVariable failed to receiver response from server", Severity.Error);
        }
        else if (!result.IsSuccess)
        {
            Snackbar.Add($"HMI client SetVariable error: {result.Message}", Severity.Error);
        }
    }

    public async ValueTask DisposeAsync()
    {
        timer.Stop();

        hmiClient.ConnectionStateChanged -= OnConnectionStateChanged;
        hmiClient.StateChanged -= OnProcessStateChanged;

        await hmiClient.StopAsync();
    }
}
