package com.qsjnic.mcu.sdk;

import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.qsjnic.mcu.contract.IMcuKeyListener;
import com.qsjnic.mcu.contract.IMcuService;
import com.qsjnic.mcu.contract.McuErrorCode;
import com.qsjnic.mcu.domain.Cmds;
import com.qsjnic.mcu.domain.Commands;
import com.qsjnic.mcu.domain.MsgType;

import java.util.concurrent.CopyOnWriteArrayList;

/** Key domain facade (msgType 0x02). */
public final class McuKeyClient {

    private static final String TAG = "McuKeyClient";

    public static final int KEY_VALUE_NONE            = 0x00;
    public static final int KEY_VALUE_MODE            = 0x01;
    public static final int KEY_VALUE_MUTE            = 0x02;
    public static final int KEY_VALUE_WORKMODE        = 0x03;
    public static final int KEY_VALUE_CALL            = 0x04;
    public static final int KEY_VALUE_VOICE_ASSISTANT = 0x05;
    public static final int KEY_VALUE_HOME            = 0x06;
    public static final int KEY_VALUE_OK              = 0x07;
    public static final int KEY_VALUE_CHANNEL_UP      = 0x08;
    public static final int KEY_VALUE_CHANNEL_DOWN    = 0x09;
    public static final int KEY_VALUE_VOLUME_UP       = 0x0A;
    public static final int KEY_VALUE_VOLUME_DOWN     = 0x0B;

    public static final int KEY_STATUS_RELEASE       = 0x00;
    public static final int KEY_STATUS_SHORT_PRESS   = 0x01;
    public static final int KEY_STATUS_STUCK         = 0x02;
    public static final int KEY_STATUS_ENCODER_LEFT  = 0x03;
    public static final int KEY_STATUS_ENCODER_RIGHT = 0x04;

    private final McuClient parent;
    private final CopyOnWriteArrayList<KeyListener> javaListeners = new CopyOnWriteArrayList<>();

    private final IMcuKeyListener.Stub aidlListener = new IMcuKeyListener.Stub() {
        @Override public void onKeyEvent(int keyValue, int keyStatus) {
            for (KeyListener l : javaListeners) safe(() -> l.onKeyEvent(keyValue, keyStatus));
        }
    };

    private boolean registeredWithService = false;

    McuKeyClient(@NonNull McuClient parent) {
        this.parent = parent;
        parent.addReadyListener(this::onServiceReady);
    }

    private void onServiceReady() {
        registeredWithService = false;
        if (!javaListeners.isEmpty()) ensureRegistered();
    }

    private void ensureRegistered() {
        if (registeredWithService) return;
        IMcuService svc = parent.getServiceUnchecked();
        if (svc == null) return;
        try {
            svc.registerKeyListener(aidlListener);
            registeredWithService = true;
            Log.i(TAG, "registered key listener with Service");
        } catch (RemoteException e) {
            Log.e(TAG, "registerKeyListener failed", e);
        }
    }

    public void addListener(@NonNull KeyListener l) {
        javaListeners.add(l);
        ensureRegistered();
    }

    public void removeListener(@Nullable KeyListener l) {
        if (l != null) javaListeners.remove(l);
    }

    public int sendKeyEvent(int keyValue, int keyStatus) {
        IMcuService svc = parent.getServiceUnchecked();
        if (svc == null) return McuErrorCode.ERR_SERVICE;
        try {
            return svc.sendKeyEvent(keyValue, keyStatus);
        } catch (RemoteException e) {
            return McuErrorCode.ERR_LINK_DOWN;
        }
    }

    public int postKeyEvent(int keyValue, int keyStatus) {
        try {
            if (parent.getServiceUnchecked() == null) return McuErrorCode.ERR_SERVICE;
            parent.postCommand(MsgType.KEY, Cmds.Key.A2M_KEY, Commands.Key.key(keyValue, keyStatus));
            return McuErrorCode.OK;
        } catch (IllegalArgumentException e) {
            return McuErrorCode.ERR_INVALID_ARG;
        }
    }

    private interface SafeCall { void run(); }

    private static void safe(SafeCall call) {
        try { call.run(); } catch (Throwable t) { Log.w(TAG, "KeyListener threw", t); }
    }
}
