/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wifi;

import android.annotation.NonNull;
import android.net.wifi.IScoreUpdateObserver;
import android.net.wifi.WifiManager;
import android.util.Log;

import com.android.modules.utils.build.SdkLevel;


/**
 * This is the callback proxy used to listen to external scorer actions triggered via
 * {@link android.net.wifi.WifiManager.ScoreUpdateObserver}.
 *
 * <p>
 * Note:
 * <li>This was extracted out of {@link WifiScoreReport} class since that is not a singleton and
 * is associated with a {@link ClientModeImpl} instance. However, this proxy sent to external scorer
 * needs to be a singleton (i.e we cannot send the external scorer a new proxy every time
 * a new primary {@link ClientModeImpl} is created).</li>
 * <li> Whenever a new primary CMM is created, it needs to register to this proxy to listen for
 * actions from the external scorer.</li>
 * </p>
 */
public class ExternalScoreUpdateObserverProxy extends IScoreUpdateObserver.Stub {
    private static final String TAG = "WifiExternalScoreUpdateObserverProxy";

    private final WifiThreadRunner mWifiThreadRunner;
    private WifiManager.ScoreUpdateObserver mCallback;

    ExternalScoreUpdateObserverProxy(WifiThreadRunner wifiThreadRunner) {
        mWifiThreadRunner = wifiThreadRunner;
    }

    /**
     * Register a new callback to listen for events from external scorer.
     */
    public void registerCallback(@NonNull WifiManager.ScoreUpdateObserver callback) {
        if (mCallback != null) {
            Log.i(TAG, "Replacing an existing callback (new primary CMM created)");
        }
        mCallback = callback;
    }

    /**
     * Unregister callback to listen for events from external scorer.
     */
    public void unregisterCallback(@NonNull WifiManager.ScoreUpdateObserver callback) {
        // mCallback can be overwritten by another CMM, when we remove it we should only
        // remove if it is the most recently registered mCallback
        if (mCallback == callback) {
            mCallback = null;
        }
    }

    @Override
    public void notifyScoreUpdate(int sessionId, int score) {
        mWifiThreadRunner.post(() -> {
            if (mCallback == null) {
                Log.wtf(TAG, "No callback registered, dropping notifyScoreUpdate");
                return;
            }
            mCallback.notifyScoreUpdate(sessionId, score);
        });
    }

    @Override
    public void triggerUpdateOfWifiUsabilityStats(int sessionId) {
        mWifiThreadRunner.post(() -> {
            if (mCallback == null) {
                Log.wtf(TAG, "No callback registered, dropping triggerUpdateOfWifiUsability");
                return;
            }
            mCallback.triggerUpdateOfWifiUsabilityStats(sessionId);
        });
    }

    @Override
    public void notifyStatusUpdate(int sessionId, boolean isUsable) {
        if (!SdkLevel.isAtLeastS()) {
            throw new UnsupportedOperationException();
        }
        mWifiThreadRunner.post(() -> {
            if (mCallback == null) {
                Log.wtf(TAG, "No callback registered, dropping notifyStatusUpdate");
                return;
            }
            mCallback.notifyStatusUpdate(sessionId, isUsable);
        });
    }

    @Override
    public void requestNudOperation(int sessionId) {
        if (!SdkLevel.isAtLeastS()) {
            throw new UnsupportedOperationException();
        }
        mWifiThreadRunner.post(() -> {
            if (mCallback == null) {
                Log.wtf(TAG, "No callback registered, dropping requestNudOperation");
                return;
            }
            mCallback.requestNudOperation(sessionId);
        });
    }

    @Override
    public void blocklistCurrentBssid(int sessionId) {
        if (!SdkLevel.isAtLeastS()) {
            throw new UnsupportedOperationException();
        }
        mWifiThreadRunner.post(() -> {
            if (mCallback == null) {
                Log.wtf(TAG, "No callback registered, dropping requestNudOperation");
                return;
            }
            mCallback.blocklistCurrentBssid(sessionId);
        });
    }
}
