namespace MinicsConsole.Helper.RawDataFilter;

public class AutoApplyAutoTurnLayer(byte mini8Index, ILog log) : IMini8DataFilter
{
    private readonly ConcurrentDictionary<byte, AutoTuneStatus> _LastStatus = [];

    public IDataSender? NextSender { get; set; }
    public IMini8Communicator? Sender { get; set; }

    private bool AutotuneFinishCheck(Mini8Output mini8Output)
    {
        if (mini8Output is null)
            return false;

        AutoTuneStatus lastActive = _LastStatus.ContainsKey(mini8Output.ChannelIndex) switch
        {
            true => _LastStatus[mini8Output.ChannelIndex],
            false => mini8Output.AutoTuneStatus
        };
        _LastStatus[mini8Output.ChannelIndex] = mini8Output.AutoTuneStatus;

        if (mini8Output.AutoTuneStatus != AutoTuneStatus.Complete || lastActive != AutoTuneStatus.Tuning)
            return false;

        return true;
    }

    private void ApplyAutotunePID(ChannelData channelData, Mini8Output mini8Output)
    {
        if (Sender is null)
        {
            log.Error($"AutoApplyAutoTurnHelper - SendSetValue Failed {channelData!.Mini8Index} Communicator Null ");
            return;
        }

        Mini8Input input = channelData.Adapt<Mini8Input>();
        input.Running_P = mini8Output.AutoTune_P;
        input.Running_I = mini8Output.AutoTune_I;
        input.Running_D = mini8Output.AutoTune_D;

        if (!Sender.SendMini8Data(channelData.ChannelIndex, input))
        {
            log.Error($"AutoApplyAutoTurnHelper - SendSetValue Failed {channelData!.Mini8Index} Send to Mini8 Failed ");
            return;
        }

        if (!Sender.SelectPID(channelData.ChannelIndex, ActiveTuneSet.Running))
        {
            log.Error($"AutoApplyAutoTurnHelper - SelectPID  Mini8-{mini8Index} Channel-{channelData.ChannelIndex} ActiveTuneSet-{ActiveTuneSet.Running}");
            return;
        }

        log.Info($"AutoApplyAutoTurnHelper - Auto apply autotune PID {input.Running_P} {input.Running_I} {input.Running_D}");
    }

    bool IDataSender.Send(Mini8Output mini8Output, ChannelData channelData, object? s)
    {
        if (this.AutotuneFinishCheck(mini8Output) is true)
            this.ApplyAutotunePID(channelData, mini8Output);

        return this.NextSender?.Send(mini8Output, channelData, default) is true;
    }
}