@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 bg-light rounded">
                                <div class="progress p-0" style="height:2px;">
                                    <span class="progress-bar" role="progressbar" style="width: @RoundToWholeNumber(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">@RoundToWholeNumber(status?.OutputVoltage)</div>
                                    <span class="text-body">
                                        V
                                    </span>
                                </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">@RoundToOneDecimal(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>Solar Power</span>
                    </h5>
                    <div class="card-body pt-0">
                        <div class="container text-center fw-bold p-0">
                            <div class="row bg-light 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">@RoundToWholeNumber(status?.PVInputVoltage)</div>
                                    <span class="text-body">
                                        V
                                    </span>
                                </div>
                                <div class="col">
                                    <div class="fs-5 text-muted">@RoundToOneDecimal(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"/>
                        Battery
                    </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">@RoundToOneDecimal(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-4 voltage">Voltage</div>
                                        <div class="text-black charge-discharge">@RoundToOneDecimal(status?.BatteryVoltage)</div>
                                        <div class="fs-4 text-black-50">V</div>
                                        <div class="fs-6 bg-white text-dark">@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;
    }

    private static double RoundToWholeNumber(double? val)
        => Math.Round(val ?? 0, 0);

    private static double RoundToOneDecimal(double? val)
        => Math.Round(val ?? 0, 1);

    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 Math.Round(status.BatteryChargeCRate, 2);

        if (status?.BatteryDischargeCRate > 0)
            return Math.Round(status.BatteryDischargeCRate, 2);

        return 0;
    }

}