using Serilog;

namespace adas_core.module.LightBeacons.Devices;

/// <summary>
/// Abstract class for LightBeacon devices. Each specific LightBeacon model should inherit from this class and implement the abstract methods for controlling the LED states (CodeBlue, CodeRed, CodeYellow, PowerOffLed).
/// </summary>
/// <param name="host">The host address of the LightBeacon device. This is typically the IP address or hostname used to connect to the device for controlling its LED states.</param>
/// <param name="password">The password used for authenticating with the LightBeacon device. This is required to establish a connection and control the device's LED states securely.</param>
public abstract class LightBeaconAbstract(string host, string password)
{
    /// <summary>
    /// The host address of the LightBeacon device. This is typically the IP address or hostname used to connect to the device for controlling its LED states.
    /// </summary>
    public string Host = host;

    /// <summary>
    /// The password used for authenticating with the LightBeacon device. This is required to establish a connection and control the device's LED states securely.
    /// </summary>
    public string Password = password;

    /// <summary>
    /// Abstract method to set the LightBeacon device to Code Blue state. This method should be implemented by each specific LightBeacon model to control the LED state accordingly.
    /// </summary> 
    /// <param name="entry">An object parameter that can be used to pass additional information or context needed for setting the LED state.</param>
    public abstract void CodeBlue(object entry);

    /// <summary>
    /// Abstract method to set the LightBeacon device to Code Red state. This method should be implemented by each specific LightBeacon model to control the LED state accordingly.
    /// </summary>
    /// <param name="entry">An object parameter that can be used to pass additional information or context needed for setting the LED state.</param>
    public abstract void CodeRed(object entry);

    /// <summary>
    /// Abstract method to set the LightBeacon device to Code Yellow state. This method should be implemented by each specific LightBeacon model to control the LED state accordingly.
    /// </summary>
    /// <param name="entry">An object parameter that can be used to pass additional information or context needed for setting the LED state.</param>
    public abstract void CodeYellow(object entry);

    /// <summary>
    /// Abstract method to power off the LED of the LightBeacon device. This method should be implemented by each specific LightBeacon model to control the LED state accordingly.
    /// </summary>
    /// <param name="entry">An object parameter that can be used to pass additional information or context needed for setting the LED state.</param>
    public abstract void PowerOffLed(object entry);

    /// <summary>
    /// Static factory method to create an instance of a specific LightBeacon device based on the provided driver name, host, and password. 
    /// This method uses reflection to dynamically instantiate the appropriate LightBeacon model class that inherits from LightBeaconAbstract.
    /// </summary>
    /// <param name="driver">The name of the driver class for the specific LightBeacon model.</param>
    /// <param name="host">The host address of the LightBeacon device.</param>
    /// <param name="password">The password for authenticating with the LightBeacon device.</param>
    /// <returns>An instance of the specific LightBeacon device, or null if the driver class is not found or cannot be instantiated.</returns>
    public static LightBeaconAbstract? GetBeaconDevice(string driver, string host, string password)
    {
        var modelType = Type.GetType($"adas_core.Drivers.LightBeacon.{driver}");
        if (modelType == null)
        {
            Log.Debug($"LightBeacon modelType not found: driver {driver}, host {host}, password {password}");
            return null;
        }

        var ctor = modelType.GetConstructor([typeof(string), typeof(string)]);
        if (ctor == null)
            return null;

        return (LightBeaconAbstract)ctor.Invoke([host, password]);
    }
}