@page "/"
@using InverterMon.Shared.Models
@using System.Text.Json
@implements IDisposable

<PageTitle>Dashboard</PageTitle>

<Loader Enabled=@(status is null)/>

@if (status is not null)
{
    <div class="container">

        @if (status.GridUsageWatts > 100)
        {
            <div class="row">
                <div class="col-sm-12">
                    <div class="card">
                        <h5 class="card-header">
                            <span class="oi oi-power-standby" aria-hidden="true"></span>
                            Grid Usage
                        </h5>
                        <div class="card-body pt-0">
                            <div class="container text-center fw-bold p-0">
                                <div class="row bg-light rounded">
                                    <div class="col">
                                        <div class="fs-1 text-danger">@status.GridUsageWatts</div>
                                        W
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        }
        <div class="row mt-2">
            <div class="col-sm-6">
                <div class="card">
                    <h5 class="card-header">
                        <span class="oi oi-lightbulb"></span>
                        <span>Output Load</span>
                    </h5>
                    <div class="card-body pt-0">
                        <div class="container text-center fw-bold p-0">
                            <div class="row rounded">
                                <div class="progress p-0" style="height:2px;">
                                    <span class="progress-bar" role="progressbar" style="width: @status.LoadPercentage%" aria-valuenow="25"
                                          aria-valuemin="0" aria-valuemax="100"></span>
                                </div>
                                <div class="col">
                                    <div class="fs-1 text-danger">@status.LoadWatts</div>
                                    W
                                </div>
                            </div>
                            <div class="row">
                                <div class="col">
                                    <div class="fs-5 text-muted">@status.OutputVoltage</div>
                                    V
                                </div>
                                <div class="col">
                                    <div class="row h-100 align-content-center">
                                        <span class="fs-6 text-muted">
                                            @(status.WorkingMode)
                                        </span>
                                    </div>
                                </div>
                                <div class="col">
                                    <div class="fs-5 text-muted">@status.LoadCurrent</div>
                                    A
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="col-sm-6">
                <div class="card mt-2 mt-sm-0">
                    <h5 class="card-header">
                        <span class="oi oi-sun" aria-hidden="true"></span>
                        <span>Solar Power</span>
                    </h5>
                    <div class="card-body pt-0">
                        <div class="container text-center fw-bold p-0">
                            <div class="row rounded">
                                <div class="progress p-0" style="height:2px;">
                                    <span class="progress-bar" role="progressbar" style="width: @status.PVPotential%" aria-valuenow="25" aria-valuemin="0"
                                          aria-valuemax="100"></span>
                                </div>
                                <div class="col">
                                    <div class="fs-1 text-success">@status.PVInputWatt</div>
                                    W
                                </div>
                            </div>
                            <div class="row">
                                <div class="col">
                                    <div class="fs-5 text-muted">@status.PVInputVoltage</div>
                                    V
                                </div>
                                <div class="col">
                                    <div class="fs-5 text-muted">@status.PVInputCurrent</div>
                                    A
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="container pt-2">
        <div class="row">
            <div class="col-sm-12">
                <div class="card">
                    <h5 class="card-header align-self-center w-100">
                        <span class="oi oi-battery-empty" aria-hidden="true"></span>
                        <span>Battery</span>
                    </h5>
                    <div class="card-body p-0 m-0">
                        <div class="container text-center m-0 p-0">
                            <div class="row m-0 p-0">
                                <div class="progress p-0" style="height:2px;">
                                    <span class="progress-bar" role="progressbar" style="width: @status.BatteryDischargePotential%" aria-valuenow="25"
                                          aria-valuemin="0" aria-valuemax="100"></span>
                                </div>
                            </div>
                            <div class="row mt-2">
                                <div class="col-4">
                                    <span class="fs-6 fw-bold text-muted charge-discharge">Charging</span>
                                    <div class="fw-bold">
                                        <div class="fs-1 text-danger">@status.BatteryChargeWatts</div>
                                        W
                                        <div class="fw-bold">
                                            <div class="fs-5 text-muted">@status.BatteryChargeCurrent</div>
                                            A
                                        </div>
                                    </div>
                                </div>
                                <div class="col-4">
                                    <div class="container bg-light rounded-1 p-1 m-0 fw-bold text-muted fs-1">
                                        <div class="fs-6 voltage">@GetChargeMode()</div>
                                        <div class="charge-discharge">@status.BatteryVoltage</div>
                                        <div class="fs-4">V</div>
                                        <div class="fs-6 crate">@GetCRate() C</div>
                                    </div>
                                </div>
                                <div class="col-4">
                                    <span class="fs-6 fw-bold text-muted charge-discharge">Discharging</span>
                                    <div class="fw-bold">
                                        <div class="fs-1 text-success">@status.BatteryDischargeWatts</div>
                                        W
                                        <div class="fw-bold">
                                            <div class="fs-5 text-muted">@status.BatteryDischargeCurrent</div>
                                            A
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
}

@code{
    private static event Action<InverterStatus?>? onStatusUpdated;
    private static event Action? onStatusRetrievalError;
    private static InverterStatus? status;

    protected override void OnInitialized()
    {
        onStatusUpdated += UpdateState;
        onStatusRetrievalError += NullifyStatus;
    }

    private void NullifyStatus()
    {
        status = null;
        StateHasChanged();
    }

    private void UpdateState(InverterStatus? s)
    {
        status = s;
        StateHasChanged();
    }

    public void Dispose()
    {
        onStatusUpdated -= UpdateState;
        onStatusRetrievalError -= NullifyStatus;
    }

    public static async Task StartStatusStreaming(string basePath)
    {
        //note: only reason we have a full-time stream download is because there's a bug in
        //      blazor-wasm that doesn't close the fetch http requests when streaming is involved.
        //      and it leads to a new stream download being created everytime a page is initialized.
        //      which leads to a memory leak/ connection exhaustion.

        using var client = new HttpClient();
        client.BaseAddress = new(basePath);
        client.Timeout = TimeSpan.FromSeconds(5);

        var retryDelay = 1000;

        while (true)
        {
            try
            {
                using var request = new HttpRequestMessage(HttpMethod.Get, "api/status");
                request.SetBrowserResponseStreamingEnabled(true);

                using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
                response.EnsureSuccessStatusCode();

                using var stream = await response.Content.ReadAsStreamAsync();

                await foreach (var s in
                               JsonSerializer.DeserializeAsyncEnumerable<InverterStatus>(
                                   stream,
                                   new JsonSerializerOptions
                                   {
                                       PropertyNameCaseInsensitive = true,
                                       DefaultBufferSize = 64
                                   }))
                {
                    onStatusUpdated?.Invoke(s);
                    retryDelay = 1000;
                }
            }
            catch (Exception)
            {
                onStatusRetrievalError?.Invoke();
                await Task.Delay(retryDelay);
                retryDelay += 500;
            }
        }
    }

    private static double GetCRate()
    {
        if (status?.BatteryChargeCRate > 0)
            return status.BatteryChargeCRate;

        if (status?.BatteryDischargeCRate > 0)
            return status.BatteryDischargeCRate;

        return 0;
    }

    private static string GetChargeMode()
        => status?.ChargeMode is ChargeMode.NONE
               ? "VOLTAGE"
               : status?.ChargeMode.ToString() ?? string.Empty;

}