using Peak.Can.Basic;
using IOModuleTestBlazor.Models;

namespace IOModuleTestBlazor.Services;

public interface ICanService
{
    bool IsConnected { get; }
    string ChannelName { get; }
    Bitrate CurrentBitrate { get; }

    /// <summary>
    /// Gets the latest received messages, indexed by CAN ID.
    /// </summary>
    IReadOnlyDictionary<uint, CanMessageDto> GetLatestMessages();

    // ── Filters ───────────────────────────────────────────────────────────────
    IReadOnlyList<CanFilter> Filters { get; }
    CanFilter AddFilter(CanFilter filter);
    bool RemoveFilter(Guid id);
    void ClearFilters();

    // ── Bitmasks ──────────────────────────────────────────────────────────────
    IReadOnlyList<CanBitmask> Bitmasks { get; }
    CanBitmask AddBitmask(CanBitmask bitmask);
    bool RemoveBitmask(Guid id);
    void ClearBitmasks();

    // ── Helpers used by the worker ────────────────────────────────────────────
    bool PassesFilter(uint messageId);
    IReadOnlyDictionary<string, double> ExtractSignals(uint messageId, byte[] data);
    void UpdateLatestMessage(CanMessageDto dto);

    // ── Channel management ────────────────────────────────────────────────────

    /// <summary>Returns all PCAN USB channels that are currently available.</summary>
    IReadOnlyList<PcanChannel> GetAvailableChannels();

    /// <summary>
    /// Asks the worker to reinitialise on the next loop iteration.
    /// Non-blocking — the actual reconnect happens asynchronously.
    /// </summary>
    void RequestReinitialize(PcanChannel channel, Bitrate bitrate);

    /// <summary>Called by the worker to pick up a pending reinit request.</summary>
    bool TryConsumePendingReinit(out PcanChannel channel, out Bitrate bitrate);

    // ── PCAN passthrough ──────────────────────────────────────────────────────
    void Initialize(PcanChannel channel, Bitrate bitrate);
    void Uninitialize();
    PcanStatus Read(out PcanMessage msg, out ulong timestamp);
    PcanStatus Write(PcanMessage msg);
}
