// Copyright (C) 2026 Jason M. Schwefel. All Rights Reserved.
package com.coldboreballisticsllc.scopedope.domain.sensor

import kotlinx.coroutines.flow.Flow

/** Fields a sensor may provide. Not every device supports all fields. */
enum class WeatherField {
    WIND_SPEED,
    WIND_DIRECTION,   // absolute compass bearing of wind source (0° = N); requires firing azimuth to convert to shooter-relative
    TEMPERATURE,
    PRESSURE,
    HUMIDITY,
}

/** A single environmental snapshot from a connected sensor. */
data class WeatherReading(
    val windSpeedMph:     Float? = null,
    val windDirectionDeg: Float? = null,  // compass bearing the wind is coming FROM (0° = N, 90° = E …)
    val temperatureF:     Float? = null,
    val pressureHpa:      Float? = null,
    val humidityPct:      Float? = null,
)

/** Connection state of a BLE weather sensor. */
sealed class SensorState {
    data object Disconnected                      : SensorState()
    data object Scanning                          : SensorState()
    data object Connecting                        : SensorState()
    data object Connected                         : SensorState()
    data class  Error(val message: String)        : SensorState()
}

/**
 * Abstraction over all BLE weather sensors.
 * Each driver implementation declares which fields it can supply via
 * [supportedFields]. The UI only auto-populates fields present in that set.
 */
interface WeatherSensorSource {
    /** Stable identifier used for `conditions_source` in .dope files. */
    val driverId: String

    /** Human-readable name shown in device picker and status bar. */
    val displayName: String

    /** Fields this driver can actually provide. */
    val supportedFields: Set<WeatherField>

    /** Current connection state. */
    val state: Flow<SensorState>

    /**
     * Live stream of readings. Emits continuously while connected.
     * Null field values indicate the sensor did not report that measurement
     * in this packet.
     */
    val readings: Flow<WeatherReading>

    /** Initiate BLE scan and connection. */
    suspend fun connect()

    /** Gracefully disconnect. */
    suspend fun disconnect()

    /**
     * Take a single snapshot of the most recent reading.
     * Returns null if not connected or no data received yet.
     */
    suspend fun snapshot(): WeatherReading?
}
